2017-10-31 2 views
0

필드가있는 클래스가 있습니다. spent_times입니다. spent_times은 목록이며이 클래스의 모든 메소드는 로깅에 유용한 일부 정보를 작성합니다.새 모듈에서 구현할 데코레이터 변경

또한 모든 함수의 실행 시간을 계산하고 spent_times에 작성하는 데코레이터가 있습니다.

이 내 장식의 실현 :

def timing(message): 
    def wrap(function): 
     def called(*args, **kwargs): 
      time_start = timer() 
      spent_time = round(timer() - time_start, 5) 

      if not args: 
       return function(*args, **kwargs), spent_time 

      obj = args[0] 
      if hasattr(obj, "spent_times"): 
       obj.spent_times.append("{}={:.5f}".format(message, spent_time)) 
       return function(*args, **kwargs) 
      else: 
       logging.warning('Decorator allows to set spent_time attribute!') 
     return called 
    return wrap 

당신이 검사가 호출하는 함수는 자기 속성이있는 경우,이 내 장식에서 볼 수 있듯이.

만약 내가 가지고있는 것이면, 그 자리에 spent_times 목록에 필요한 정보를 쓸 수 있습니다. 그렇지 않으면 데코레이터가 실행 및 함수 자체에 소비 한 시간을 반환합니다.

이 모듈은 하나의 모듈과 두 번째 케이스 (자기이 발견되지 않음)에서이 모듈의 다른 함수에 속하며, consum_time 목록이 정의 된 클래스에 속하지 않지만이 모듈을 실행합니다 내 수업 내부, 그래서 예를 들어 다음과 같은 구조를 실현할 수 있어요 :

이 "외부"기능의 선언입니다

def calc_users(requests, priority): 
    # ..... 

그리고 내 수업 안에 내가 그것을 실행하고 내 spent_time 목록이 업데이트

길 :

response, spent_time = calc_users(requests, priority) 
self.class_obj.spent_times.append("user_calculation={:.5f}".format(spent_time)) 

매우 좋지는 않지만 적어도 효과가 있습니다.

지금 내 클래스의 몇 가지 기능을 새 모듈 새 모듈로 이동 했으므로 동일한 장식 자 타이밍을 사용하고 싶습니다.

새로운 모듈에서 이러한 타이밍 구현을 구현할 수있는 사람이 있습니까? 모르겠다. 이제 spent_times 목록을 업데이트하려면 어떻게해야합니까?

이 두 모듈은 동시에 작동하며 클래스의 객체를 생성하여 새로운 모듈에 인수로 전달할 수 없습니다. (이해할 수있는 한) 두 객체가 있고 spend_times는 업데이트되지 않기 때문입니다. 바르게.

어쨌든 spent_times에 대한 참조를 전달하는 방법이있을 수 있지만,이 경우 공유 책임 원칙이 깨질 것이라고 생각하기 때문에 새 모듈에서 내 함수의 인수를 변경하고 싶지 않습니다 (데코레이터는 로깅, 동작을위한 기능).

데코레이터를 개선하는 방법이나 spent_times 목록을 새 모듈로 전달하는 방법은 무엇입니까?

도움이 될 것입니다.

P.

아마도 spent_times을 전역 변수로 만드시겠습니까? (최악의 경우)

답변

1

전역 목록은 괜찮은 것처럼 보이지만 클래스를 사용하고 인스턴스화 후에 클래스를 삭제하여 싱글 톤을 만들 수도 있습니다.이것은 또 다른 다른 인스턴스를 만들 수 없습니다 :

# mymodule.py 

from timeit import default_timer as timer 

class Timing(object): 
    def __init__(self): 
     self.spent_times = [] 

    def __call__(self, message): 
     def wrap(function): 
      def called(*args, **kwargs): 
       time_start = timer() 
       spent_time = round(timer() - time_start, 5) 
       self.spent_times.append("{}={:.5f}".format(message, spent_time)) 
       return function(*args, **kwargs) 
      return called 
     return wrap 

timing = Timing() 
del Timing # prevent another instance 

지금 다른 모듈에서 가져옵니다

from mymodule import timing 

@timing('Hello') 
def add(a, b): 
    return a + b 

특별한 방법 __call__이 클래스의 인스턴스는 함수처럼 행동한다, 즉,을은 ()으로 호출합니다. 전역 변수 대신 self.attr을 사용할 수 있다는 이점이 있습니다.

인스턴스화 후 클래스를 삭제하면 다른 인스턴스가 작성되지 않습니다. 이를 싱글 톤이라고합니다. timing을 장식 자로 얼마나 자주 사용 하든지 관계없이 동일한 목록에서 모든 시간이 끝납니다.

+0

Vielen Dank! Das ist aber nicht so leich zu verstehen .. (감사합니다! 이해하기 쉽지 않지만) – John

+0

몇 가지 추가 설명이 추가되었습니다. –

+0

자세한 설명을 가져 주셔서 감사합니다. 여기서 다른 작업을 보았습니다. mymodule.py에서 삭제 작업을 결정해야합니다. 타이밍을 삭제해야하는 순간을 어떻게 알 수 있습니까? – John

관련 문제