Python:装饰的staticmethod接收不可调用的方法

时间:2011-03-17 21:21:51

标签: python decorator

我在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

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

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

好吧,无论你是否认为它是一个错误,它都是documented

  

静态方法对象提供了一种破坏转换的方法   函数对象到方法对象   如上所述。静态方法   object是任何其他的包装器   对象,通常是用户定义的方法   宾语。当一个静态方法对象是   从类或类中检索   实例,实际返回的对象   是包装的对象,不是   受任何进一步的转变。   静态方法对象不是   他们自己可以打电话,虽然   他们通常包裹的物品。静态的   方法对象由。创建   内置的staticmethod()构造函数。

答案 2 :(得分:1)

我编写了自己的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的这个实现仍然允许你将静态方法作为包装函数的属性来调用。)