1

请原谅我对描述符和装饰器的互换使用。我可能在这里有一些错误。

我想编写(很多)类,这些类以声明方式指定它们的方法,如下所示:

class Foo:

    @method_metadata(0,1,2)
    def some_method(self,input):
        print("I received some input: "+input)

目的不是改变方法的行为,只是注册 (0,1,2) 与此方法相关联。

我编写了以下描述符来实现这一点。它给了我三分之二的我需要的东西:

class method_metadata:

    # 1 - I need to gather three things here: the parameters passed into the method descriptor (0,1,2) in my case
    # 2 - A reference to the method so I can call it later
    # 3 - The class that the method lives in - this is the one I can't figure out

    def __init__(self,*collection_args):

        # Achieved #1 here
        self.collection_args = collection_args

    def __call__(self,decorated_function):

        #Achieved #2 here:
        self.decorated_method = decorated_method

        #I'm not sure how to achieve #3 here.

        # inspect.getmembers(decorated_function) showed some promise, not sure if I should pursue that.

        # Alternatively, if I put a descriptor on the class that contains the method, I can iterate through the attributes and get what I need.  That'll be my fall-back solution but in my case it causes a bit of a problem because some attributes aren't happy to be read yet (they throw assertions because they're not initialized, etc).

        return decorated_function

有什么想法可以在 method_metadata 中找出所讨论的方法属于 Foo 类吗?

PS - 我在 Python 3.2 上,不需要向后兼容。

4

1 回答 1

0

在定义类成员(函数或类数据成员)时,它不知道封闭类。关键字在 Python 中的工作方式是语句class体中的class表达式被求值,打包到 a 中dict,然后作为 . 传递给元类(默认情况下,typemetaclass(classname, bases, members)。在评估它们时(包括应用装饰器),无法引用它们最终将被添加到的类。

“处理”需要了解封闭类的元数据的方法是使用元类或类装饰器;任何一个:

class Foo(metaclass=supporting_metaclass):

或者

@supporting_class_decorator
class Foo:

效果上没有太大区别,类装饰器的优点是你从一个完全指定的类开始,而不是自己构建它,所以写起来更简单;此外,类装饰器可以链接。

无论哪种方式,您都需要在元/装饰类机器和方法装饰器之间建立某种程度的合作,并且最好放在金丝雀中,这样您就不会忘记其中一个(例如,使装饰方法非- 可在没有元/类装饰器的情况下调用)。

于 2012-07-23T09:34:48.993 回答