Python 装饰器作为静态方法
我正在尝试编写一个 python 类,它使用需要实例状态信息的装饰器函数。这是按预期工作的,但是如果我明确地将装饰器设为静态方法,则会收到以下错误:
Traceback (most recent call last):
File "tford.py", line 1, in <module>
class TFord(object):
File "tford.py", line 14, in TFord
@ensure_black
TypeError: 'staticmethod' object is not callable
为什么?
这是代码:
class TFord(object):
def __init__(self, color):
self.color = color
@staticmethod
def ensure_black(func):
def _aux(self, *args, **kwargs):
if self.color == 'black':
return func(*args, **kwargs)
else:
return None
return _aux
@ensure_black
def get():
return 'Here is your shiny new T-Ford'
if __name__ == '__main__':
ford_red = TFord('red')
ford_black = TFord('black')
print ford_red.get()
print ford_black.get()
如果我只是删除行 @staticmethod
,一切正常,但我不明白为什么。它不应该需要 self
作为第一个参数吗?
I'm trying to write a python class which uses a decorator function that needs information of the instance state. This is working as intended, but if I explicitly make the decorator a staticmetod, I get the following error:
Traceback (most recent call last):
File "tford.py", line 1, in <module>
class TFord(object):
File "tford.py", line 14, in TFord
@ensure_black
TypeError: 'staticmethod' object is not callable
Why?
Here is the code:
class TFord(object):
def __init__(self, color):
self.color = color
@staticmethod
def ensure_black(func):
def _aux(self, *args, **kwargs):
if self.color == 'black':
return func(*args, **kwargs)
else:
return None
return _aux
@ensure_black
def get():
return 'Here is your shiny new T-Ford'
if __name__ == '__main__':
ford_red = TFord('red')
ford_black = TFord('black')
print ford_red.get()
print ford_black.get()
And if I just remove the line @staticmethod
, everything works, but I do not understand why. Shouldn't it need self
as a first argument?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这不是
staticmethod
应该如何使用的。staticmethod
对象是返回包装对象的描述符,因此它们仅当作为classname.staticmethodname
访问时才有效。 示例打印
在
A
范围内,您始终会得到后一个对象,该对象不可调用。我强烈建议将装饰器移至模块范围——它似乎不属于类内部。如果您想将其保留在类中,请不要将其设为
staticmethod
,而是简单地将其del
放在类主体的末尾——这并不是为了在这种情况下可以从类外部使用。This is not how
staticmethod
is supposed to be used.staticmethod
objects are descriptors that return the wrapped object, so they only work when accessed asclassname.staticmethodname
. Exampleprints
Inside the scope of
A
, you would always get the latter object, which is not callable.I'd strongly recommend to move the decorator to the module scope -- it does not seem to belong inside the class. If you want to keep it inside the class, don't make it a
staticmethod
, but rather simplydel
it at the end of the class body -- it's not meant to be used from outside the class in this case.Python 类是在运行时评估类声明的内容后创建的。通过将所有声明的变量和函数分配给一个特殊的字典并使用该字典调用 type.__new__ 来评估该类(请参阅自定义类创建)。
因此,
相当于:
当您使用 @staticmethod 注解一个方法时,在使用
type.__new__
创建类之后会发生一些特殊的魔法。在类声明范围内,@staticmethod 函数只是 staticmethod 对象的实例,您无法调用它。装饰器可能应该在同一模块中的类定义上方或在单独的“装饰”模块中声明(取决于您有多少个装饰器)。一般来说,装饰器应该在类之外声明。一个值得注意的例外是属性类(请参阅 properties)。在您的情况下,如果您有类似颜色类的内容,那么在类声明中使用装饰器可能是有意义的:Python classes are created at runtime, after evaluating the contents of the class declaration. The class is evaluated by assigned all declared variables and functions to a special dictionary and using that dictionary to call
type.__new__
(see customizing class creation).So,
is equivalent to:
When you annotate a method with @staticmethod, there is some special magic that happens AFTER the class is created with
type.__new__
. Inside class declaration scope, the @staticmethod function is just an instance of a staticmethod object, which you can't call. The decorator probably should just be declared above the class definition in the same module OR in a separate "decorate" module (depends on how many decorators you have). In general decorators should be declared outside of a class. One notable exception is the property class (see properties). In your case having the decorator inside a class declaration might make sense if you had something like a color class:解决方案确实存在!
问题是尝试用作装饰器的静态方法实际上是 staticmethod 对象并且不可调用。
解决方案:staticmethod对象具有方法
__get__
,它接受任何参数并返回真实方法:python 文档 Python 3.5 及更高版本:我提供的最小解决方案是:
将打印 (2, 4)
Solution does exist!
Problem is that Static method that is trying to be used as decorator is in fact staticmethod object and is not callable.
Solution: staticmethod object has method
__get__
which takes any argument and returns real method: python documentation Python 3.5 and up:Min solution I came with is:
Will print (2, 4)
ensure_black
返回一个未由@staticmethod
修饰的_aux
方法您可以将非静态方法返回给 static_method
http://docs.python.org/library/functions.html#staticmethod
ensure_black
is returning a_aux
method that isn't decorated by@staticmethod
You can return a non-static method to a static_method
http://docs.python.org/library/functions.html#staticmethod