使用装饰器链在程序出口处注册类方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用装饰器链在程序出口处注册类方法相关的知识,希望对你有一定的参考价值。
我有一个类,它的一个属性是我想在程序退出时运行的类方法。这个直接的想法:
import atexit
class Foo:
@atexit.register
@classmethod
def foo(cls):
pass
引发以下异常:
Traceback (most recent call last):
File "test.py", line 3, in <module>
class Foo:
File "test.py", line 5, in Foo
@classmethod
TypeError: the first argument must be callable
另一个直接的想法(注意改变装饰器的评估顺序):
import atexit
class Foo:
@classmethod
@atexit.register
def foo(cls):
pass
引发以下异常:
Error in atexit._run_exitfuncs:
TypeError: foo() missing 1 required positional argument: 'cls'
我对装饰器的概念很陌生。
- 有没有简单的方法如何修复此代码仍然使用装饰链?
- 如果没有,您会建议什么作为替代解决方案?
答案
首先你应该阅读How does a classmethod object work?的答案
但是看到以下代码的输出会很有趣:
def mydeco(func):
print(repr(func))
return func
class Foo:
@mydeco
@classmethod
def foo(cls):
pass
print(repr(Foo.foo))
如果你运行它,你会看到
<classmethod object at 0x6ffffd1dc18>
<bound method Foo.foo of <class '__main__.Foo'>>
所以第一行来自mydeco()
装饰器,第二行来自底部的print()
语句。你看他们是不同的。它们不同的原因是因为classmethod
不像你期望的函数装饰器。它不会给你一个函数,而是一个classmethod
对象,它不可调用。然而,与此同时,包含它的类Foo
记得在Foo.__dict__
中,当你回想起装饰类方法时,它会给你一个可调用的方法。
仅仅因为classmethod
对象不可调用。你不能用atexit.register
包装它。 staticmethod
的类似案例。
所以现在你应该意识到,要将它注册到atexit
,你可以在课外进行,如下所示:
import atexit
class Foo:
@classmethod
def foo(cls):
pass
atexit.register(Foo.foo)
以上是关于使用装饰器链在程序出口处注册类方法的主要内容,如果未能解决你的问题,请参考以下文章