오브젝트 obj
을 사용하는 새로운 함수/메소드를 작성하는 데코레이터를 만들고 싶습니다. 데코 레이팅 된 객체가 함수 인 경우 함수를 만들 때 obj
을 인스턴스화해야합니다. 데코 레이팅 된 객체가 메서드 인 경우 새 obj
을 인스턴스화하고 메서드가 데코 레이팅 된 클래스의 각 인스턴스에 바인딩해야합니다. 데코레이터가 함수 문서를 수정하기 때문에 장식을 __init__
에 넣을 수 없습니다. 지금은 이런 일을 가지고 있지만 그것은 단지 내가 원하는하지 않은, 한 번 time
을 인스턴스화인스턴스화 시간 변수가있는 파이썬 데코레이터?
__all__ = ['dec', 'A']
from time import time
import inspect
def dec(f):
obj = time() # want to set on object instantiation
def new(*args, **kwargs):
f(*args, **kwargs) # Validate against definition so it doesn't go
# out of sync
print obj
# ...
try:
d = inspect.getsourcelines(f)
except IOError:
d = "<unable to fetch definition>"
else:
d = d[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
new.__doc__ = d + "\n" + (f.__doc__ or '')
return new
class A(object):
@dec
def f(self, x):
"""something"""
print '%s.f(%s)' % (self, x)
if __name__ == '__main__':
A().f(123)
A().f(123)
A().f(123)
이 문제를 해결하기 위해 내 생각은 장식에 전달 된 객체가 인수
self
걸리는 경우 만약 그렇다면, 확인하는 것입니다
이미 존재하지 않으면 obj
을 self
에 바인드하고 self.obj
을 사용하는 메소드를 리턴하십시오. 그리고 장식 자에게 건네지는 객체에 대해 self
인수가 없으면 장식 자 안에 obj
을 인스턴스화하고이를 사용하는 함수를 반환하십시오.
그러나 ... 내 진짜 장식 자 때문에 list
에서 파생되고 __call__
특성을 가진 개체를 반환하기 때문에 내가 말한 것은 실제로 나를 위해 작동하지 않습니다. 또한 실제 장식 자의 경우 self
은 인스턴스 변수를 사용하지 않기 때문에 장식 된 객체에 정의되어 있지 않습니다. (내가 무엇인지 실제로 장식은 외부 객체가 구독하는 이벤트이며, 이벤트에는 서명이 문서화되어 있음).
편집 : 사실 list
하위 클래스 인스턴스가 인스턴스에 바인딩되도록하여 __call__
속성이 클래스 인스턴스를 암시 적으로 (예 : 일반 인스턴스 메소드에서와 같이) 수신하는 경우 완벽한 솔루션이 될 것입니다. 내가 원래하는 방법을 알아 내려고 애썼다. 하지만 self
특성을 사용하여 데코 레이팅 된 메서드를 정의 할 필요가없는 더 나은 솔루션이있을 수 있습니까? 둘 중 하나가 완벽합니다.
나는 분명히 그것이 내가 원하는 것이 아니라고 말했다. 내 데코레이터는 데코 레이팅 된 함수의 문서를 변경합니다. 데코레이션을'__init__'에 넣으면 발생하지 않습니다. –
@ Longpoke : 왜'__doc__'가 중요한가요? '__doc__'의 일부를 생성하기 위해 메타 클래스를 사용하지 않는 이유 –
데코레이터는이 함수를'list'의 서브 클래스로 변환하고'__call__'을 추가합니다. 그건'__doc__'을 파괴하므로 새로 만든 객체로 복사합니다. 나는 메타 클래스에 대한 경험이 없지만 여기서 도움이 될지 확신하지 못합니다. 이미 abc.ABCMeta를 사용하고 있는데 한 번에 두 개의 메타 클래스를 사용할 수 있습니까? 필자가 정말로 필요로하는 것은'self '를 받기위한'__call__' 메소드 (리스트 서브 클래스에 추가)를위한 것입니다. 그래서 나는 상태를 유지할 수 있습니다. –