2011-03-17 80 views
5

我在装饰Python中的静态方法时遇到了一些问题。我想下面的代码最能代表我的问题:Python:装饰静态方法recive不可调用方法

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是如何实现的,所以我无法评估这种方法的成功。

+0

请注意,您必须使用静态方法的新样式类才能在实例上调用,因为它使用了描述符。 – 2011-03-17 21:33:37

+2

要使其工作,只需更改描述符的顺序。 – 2011-03-17 21:36:23

回答

4

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

+0

啊,这是有道理的。谢谢。 – 2011-03-17 21:37:34

4

那么,你是否认为这是一个错误或不是,它是documented

静态方法对象提供 函数对象的转变击败至方法的对象的方式上述 。静态方法 对象是围绕任何其他对象的包装,通常是用户定义的方法 对象。当从一个类或一个类 实例中检索到的静态方法对象是 时,实际返回的对象 是被包装的对象,它不受 的约束,可以进行任何进一步转换。 静态方法对象不是 本身可以调用,尽管它们通常包装的对象是 。静态 方法对象由 内置的staticmethod()构造函数创建。

0

我写了我自己实现的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,但在实践中,使可调用的函数为类的属性,实例属性,甚至是功能属性(即,如果你已经在装饰函数中包装了你的类,静态方法的这个实现仍然允许你把你的静态方法作为包装函数的属性)。