2

我正在尝试编写一个修改其类状态的类方法装饰器。我目前在实施它时遇到了麻烦。

附带问题:装饰器什么时候被调用?它是在类被实例化时加载还是在类读取时加载?

我想要做的是:

class ObjMeta(object):
    methods = []

    # This should be a decorator that magically updates the 'methods'
    # attribute (or list) of this class that's being read by the proxying
    # class below.
    def method_wrapper(method):
        @functools.wraps(method)
        def wrapper(*args, **kwargs):
            ObjMeta.methods.append(method.__name__)
            return method(*args, **kwargs)
        return wrapper

    # Our methods
    @method_wrapper
    def method1(self, *args):
        return args

    @method_wrapper
    def method2(self, *args):
        return args


class Obj(object):

    klass = None

    def __init__(self, object_class=ObjMeta):
        self.klass = object_class
        self._set_methods(object_class)

    # We dynamically load the method proxies that calls to our meta class
    # that actually contains the methods. It's actually dependent to the 
    # meta class' methods attribute that contains a list of names of its
    # existing methods. This is where I wanted it to be done automagically with
    # the help of decorators
    def _set_methods(self, object_class):
        for method_name in object_class:
            setattr(self, method_name, self._proxy_method(method_name))

    # Proxies the method that's being called to our meta class
    def _proxy_method(self, method_name):
        def wrapper(*fargs, **fkwargs):
            return getattr(self.klass(*fargs, **fkwargs), method_name)
        return wrapper()

我认为在类中手动编写方法列表很丑,所以也许装饰器会解决这个问题。

这是我正在将 underscore.js 移植到 python 的开源项目。我知道它说我应该只使用 itertools 或其他东西。我这样做只是为了热爱编程和学习。顺便说一句,项目托管在这里

谢谢!

4

1 回答 1

1

这里有一些问题。

当方法本身被调用时,内部包装器中的任何内容都会被调用。基本上,您正在用该函数替换该方法,该函数包装了原始函数。因此,您的代码会在每次调用时将方法名称添加到列表中,这可能不是您想要的。相反,该附加应该在method_wrapper级别上,即在内部包装之外。这在定义方法时调用,这发生在第一次导入包含该类的模块时。

第二个错误是你从来没有真正调用过这个方法——你只是简单地返回它。而不是return method您应该返回使用提供的参数调用方法的值 - return method(*args, **kwargs)

于 2012-07-03T09:54:04.347 回答