Decorating methods: AttributeError: 'function' object has no attribute '__self__'?
我正在与
每次计划方法完成时都应调用此类方法。虽然我在每个方法的末尾添加了
我编写了一个类修饰器,然后将它应用到我的主类的一些方法中,编写了其余的逻辑和所有这些。但是当尝试在我的项目上测试我的更改时,我得到一个例外:
1 | AttributeError: 'function' object has no attribute '__self__' |
不知怎么地,修饰我的方法使它成为一个函数。这是我无法理解的,为什么会这样?我怎么能在不放弃装修工人的情况下解决这个问题呢?
下面是我要做的一个最小、完整和可验证的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import asyncio from datetime import datetime class thinkagain: loop = asyncio.get_event_loop() def __init__(self, f): self.fun = f self.class_ = f.__self__ def __call__(self): self.fun(*args, **kwords) # everything in Python is an object setattr(self.fun,"called", datetime.utcnow()) self.loop.call_later(self.class_.think, 5 * 60) class DoSomething: loop = asyncio.get_event_loop() @thinkagain def think(self): attr = getattr(self.dosomething,"called") if attr: elapsed = attr - datetime.utcnow() seconds = elapsed.seconds else: seconds = 99999 if seconds >= 20 * 60: self.loop.call_soon(self.dosomething) @thinkagain def dosomething(self): print("I did something awesome!") loop = asyncio.get_event_loop() something = DoSomething() loop.call_soon(something.think) loop.run_forever() |
号
我得到的例外是:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Python 3.5.1 (default, Dec 7 2015, 13:41:59) [GCC 5.2.0] on linux Type"help","copyright","credits" or"license" for more information. >>> Traceback (most recent call last): File"<stdin>", line 1, in <module> File"/tmp/mcve.py", line 19, in <module> class DoSomething: File"/tmp/mcve.py", line 22, in DoSomething @thinkagain File"/tmp/mcve.py", line 10, in __init__ self.class_ = f.__self__ AttributeError: 'function' object has no attribute '__self__' >>> |
观看装饰,格雷厄姆邓布利顿高级装饰设计师的方法,探讨各种装饰风味和技术的内部实现。Highly recommended.
Relevant module he introduced at the end:https://github.com/grahamdumpleton/wrapt
我用两个版本修改你的例子。下一个版本的百叶窗属性根据你的要求直接在方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | from datetime import datetime class thinkagain: def __init__(self, f): # Plain function as argument to be decorated self.func = f def __get__(self, instance, owner): self.instance_ = instance return self.__call__ def __call__(self, *args, **kwargs): """Invoked on every call of any decorated method""" # set attribute directly within bound method bound_method = getattr(self.instance_, self.func.__name__) bound_method.__dict__['called'] = datetime.utcnow() # returning original function with class' instance as self return self.func(self.instance_, *args, **kwargs) class DoSomething_A: @thinkagain def think(self, *args, **kwargs): print(' %s' % locals()) print(self.think.called, args, kwargs) self.dosomething() @thinkagain def dosomething(self): print('%s ' % ('-'*30), locals()) print("%s I did something awful" % self.dosomething.called) |
第二个版本的清洁剂和它的皮肤保存在方法中的属性,并直接在程序中分配。
ZZU1
两个都产生同样的愿望:
1 2 3 4 5 6 | >>> something = DoSomething_A().think(1, 2) {'args': (1, 2), 'kwargs': {}, 'self': <__main__.DoSomething_A object at 0x10209f128>} 2015-12-26 04:13:25.629887 (1, 2) {} ------------------------------ {'self': <__main__.DoSomething_A object at 0x10209f128>} 2015-12-26 04:13:25.647476 I did something awful |
和
1 2 3 4 5 6 | >>> something = DoSomething_B().think('arg_a', 'arg_b') {'args': ('arg_a', 'arg_b'), 'kwargs': {}, 'self': <__main__.DoSomething_B object at 0x10209f208>} 2015-12-26 04:13:25.648039 ------------------------------ {'self': <__main__.DoSomething_B object at 0x10209f208>} 2015-12-26 04:13:25.648390 |
Somehow, decorating my method made it a function.
不正确功能是创建的,然后是装饰,然后成为一种方法。你需要写一个文件,抓住