方法描述符提供元数据但无法获取方法所在的类

时间:2012-07-23 08:15:29

标签: python decorator descriptor

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

我想编写(很多)类,以声明方式指定有关其方法的内容:

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,不需要向后兼容。

1 个答案:

答案 0 :(得分:0)

在定义类成员(函数或类数据成员)时,它不知道封闭类。 class关键字在Python中的工作方式是评估class语句正文中的表达式,将其打包到dict中,然后传递给元类(默认情况下为{{ 1}})type。在他们被评估的时候(包括应用装饰器),没有办法引用他们最终将被添加到的类。

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

metaclass(classname, bases, members)

class Foo(metaclass=supporting_metaclass):

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

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