Python: Decorated staticmethod receives non

I'm having a little problem decorating a static method in Python. I think the following code best represents my problem:

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

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

# outputs False

print callable(Foo.bar) 
# outputs True

This seems to be a bug. I imagine it arises because when the method Foo.bar is passed to the decorator, it is a function, not a method. That is the only reason I can see for it not being callable, for if we decorate a standard function, it is not callable, as shown below.

@staticmethod
def function():
    return

print callable(function) 
# outputs False

So is this a true bug in implementation of the staticmethod decorator, and/or are there any simple workarounds? I did think of writing a decorator to asign a __call__ attribute, but I don't know how callable is implemented, so I can't gauge the sucess of such a method.


Methods are functions. But staticmethod objects aren't. They are descriptors, so there's extra magic that gives you a callable when you access it as Cls.static_method , but this magic can't hide anything when you use (ie pass to decorator) static_method inside the body of Cls . You can't really hack your way around this, at least not cleanly. A much simpler solution is reordering the decorators such that staticmethod get applied last - ie put it at the top, above all other decorators.


Well, whether you consider it a bug or not, it's documented:

Static method objects provide a way of defeating the transformation of function objects to method objects described above. A static method object is a wrapper around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation. Static method objects are not themselves callable, although the objects they wrap usually are. Static method objects are created by the built-in staticmethod() constructor.


I wrote my own implementation of staticmethod that is callable and this seems to solve this problem nicely.

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)

This doesn't use the descriptor protocol and as such behaves very differently than the builtin staticmethod internally, however in practice it makes functions callable as class attributes, instance attributes, and even as function attributes (ie, if you've wrapped your class in a decorating function, this implementation of staticmethod will still allow you to call your static methods as attributes on the wrapping function).

链接地址: http://www.djcxy.com/p/54178.html

上一篇: 风格和新

下一篇: Python:装饰的静态方法接收非