【问题标题】:Python: Decorated staticmethod receives non-callable methodPython:装饰的静态方法接收不可调用的方法
【发布时间】:2011-03-17 21:21:50
【问题描述】:

我在装饰 Python 中的静态方法时遇到了一点问题。我认为以下代码最能代表我的问题:

def decorator(func):
    print callable(func)
    return func

class Foo():
    @decorator
    @staticmethod
    def bar():
        return

# outputs False

print callable(Foo.bar) 
# outputs True

这似乎是一个错误。我想它的出现是因为当 Foo.bar 方法被传递给装饰器时,它是一个函数,而不是一个方法。这是我可以看到它不可调用的唯一原因,因为如果我们装饰一个标准函数,它就不可调用,如下所示。

@staticmethod
def function():
    return

print callable(function) 
# outputs False

那么这是实现 staticmethod 装饰器的真正错误,和/或有任何简单的解决方法吗?我确实想过写一个装饰器来分配一个__call__属性,但是我不知道callable是如何实现的,所以我无法衡量这种方法的成功。

【问题讨论】:

  • 请注意,staticmethod 必须使用新样式类才能在实例上也可调用,因为它使用描述符。
  • 要使其工作,只需更改描述符的顺序即可。

标签: python decorator


【解决方案1】:

方法函数。但staticmethod 对象不是。它们是descriptors,所以当您以Cls.static_method 访问它时,会有额外的魔法给您一个可调用对象,但是当您在@987654325 的主体内使用(即传递给装饰器)static_method 时,这种魔法无法隐藏任何东西@。你不能真正解决这个问题,至少不能干净。一个更简单的解决方案是重新排序装饰器,使 staticmethod 最后应用 - 即将它放在顶部,高于所有其他装饰器。

【讨论】:

    【解决方案2】:

    好吧,不管你是否认为它是一个错误,它都是documented

    静态方法对象提供了一种方法来克服 函数对象到方法对象 如上所述。静态方法 对象是任何其他对象的包装器 对象,通常是用户定义的方法 目的。当一个静态方法对象是 从类或类中检索 实例,实际返回的对象 是被包裹的对象,不是 受到任何进一步的转变。 静态方法对象不是 它们本身是可调用的,虽然 他们包装的对象通常是。静止的 方法对象由 内置 staticmethod() 构造函数。

    【讨论】:

      【解决方案3】:

      我编写了自己的staticmethod 实现可调用的,这似乎很好地解决了这个问题。

      class staticmethod(object):
          """Make @staticmethods play nice with @memoize."""
      
          def __init__(self, func):
              self.func = func
      
          def __call__(self, *args, **kwargs):
              """Call the static method with no instance."""
              return self.func(*args, **kwargs)
      

      这不使用描述符协议,因此其行为与内置的 staticmethod 内部非常不同,但实际上它使函数可作为类属性、实例属性甚至函数属性调用(即,如果你'已经将你的类包装在一个装饰函数中,这个 staticmethod 的实现仍然允许你调用你的静态方法作为包装函数的属性)。

      【讨论】:

        猜你喜欢
        • 2018-05-07
        • 1970-01-01
        • 2011-09-18
        • 2015-02-21
        • 1970-01-01
        • 2020-06-03
        • 1970-01-01
        • 2018-01-04
        • 2010-12-31
        相关资源
        最近更新 更多