请原谅我对描述符和装饰器的交换使用。我可能在这里有些错误。
我想编写(很多)类,以声明方式指定有关其方法的内容:
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,不需要向后兼容。
答案 0 :(得分:0)
在定义类成员(函数或类数据成员)时,它不知道封闭类。 class
关键字在Python中的工作方式是评估class
语句正文中的表达式,将其打包到dict
中,然后传递给元类(默认情况下为{{ 1}})type
。在他们被评估的时候(包括应用装饰器),没有办法引用他们最终将被添加到的类。
需要了解封闭类的“处理元数据”的方法是使用元类或类装饰器;之一:
metaclass(classname, bases, members)
或
class Foo(metaclass=supporting_metaclass):
效果上没有太大区别,类装饰器的优点是你从一个完全指定的类开始,而不是自己构建它,所以往往更容易编写;也可以将类装饰器链接起来。
无论哪种方式,您都需要在元/装饰类机器和方法装饰器之间建立一定程度的合作,并且最好放入金丝雀,这样您就不会忘记其中一个(例如,装饰方法不可调用,没有meta / class装饰器)。