python装饰器将函数添加到对象上的列表中

python装饰器将函数添加到对象上的列表中,python,python-decorators,Python,Python Decorators,在python中,我需要在我的类上创建一个属性列表,我可以序列化这些属性,在类的顶部列出这些属性是很麻烦的。相反,我希望以使用@property的相同方式使用decorator,例如: class MyClass(object): # I dont like having to do this for example #__list_of_props_to_serialise__ = ['my_prop',] @property @serialise

在python中,我需要在我的类上创建一个属性列表,我可以序列化这些属性,在类的顶部列出这些属性是很麻烦的。相反,我希望以使用@property的相同方式使用decorator,例如:

class MyClass(object):

    # I dont like having to do this for example
    #__list_of_props_to_serialise__ = ['my_prop',]

    @property
    @serialise
    def my_prop(self):
        return "this is my property"

    def serialise(self):
        return {f: self.getattr(f) for f in self.__list_of_props_to_serialise__}
其中,构建类时,decorator会更新对象上的
\u props\u to\u serialise\uuu的列表,因此我不需要在开始时注释掉的行

问题是,当我开始编写decorator时,在实际调用
my_prop
函数之前,我无法访问该类或对象,因此无法添加它。我是否“做错了”,是否有更好的方法来做这件事,或者是否可以通过某种方式来做

如果可以做到这一点,请显示一些装饰功能,我可以使用,否则,如果有更好的方法,请给出一个例子


谢谢。

只需向函数对象添加标记属性,而不是建立列表。然后枚举类上具有该属性的所有函数

因为这里有
property
对象,所以只能在属性对象的getter上找到该属性,所以需要确保访问类型而不是实例上的属性,然后分别触发getter:

def serialise(func):
    func._do_serialise = True
    return func

def serialisables(obj):
    cls = type(obj)
    cls_attrs = ((name, getattr(cls, name, None)) for name in dir(obj))
    return {name: getattr(obj, name) for name, attr in cls_attrs
            if isinstance(attr, property) and getattr(attr.fget, '_do_serialise', False)}
演示:


不必建立列表,只需向函数对象添加标记属性即可。然后枚举类上具有该属性的所有函数

因为这里有
property
对象,所以只能在属性对象的getter上找到该属性,所以需要确保访问类型而不是实例上的属性,然后分别触发getter:

def serialise(func):
    func._do_serialise = True
    return func

def serialisables(obj):
    cls = type(obj)
    cls_attrs = ((name, getattr(cls, name, None)) for name in dir(obj))
    return {name: getattr(obj, name) for name, attr in cls_attrs
            if isinstance(attr, property) and getattr(attr.fget, '_do_serialise', False)}
演示:


您可以在类之外编写decorator,使用与MyClass类型对象相对应的参数“self”:

def serialise(func):
    def wrapper(self, *args, **kwargs):
        if func.__name__ not in self.serialisables:
            self.serialisables.append(func.__name__)
            print("Adding " + func.__name__)
        return func(self, *args, **kwargs)
    return wrapper
然后在MyClass中初始化序列化文件列表:

class MyClass(object):

    def __init__(self):
        self.serialisables = []

    @property
    @serialise
    def my_prop(self):
        return "this is my property"
使用该属性时,其名称将添加到serialisables属性中:

>>> c = MyClass()
>>> c.my_prop
Adding my_prop
this is my property
>>> c.serialisables
['my_prop']
但是,只有在使用c.my_prop时,才会添加属性的名称:

>>> c = MyClass()
>>> c.serialisables
[]

您可以在类之外编写decorator,使用与MyClass类型对象相对应的参数“self”:

def serialise(func):
    def wrapper(self, *args, **kwargs):
        if func.__name__ not in self.serialisables:
            self.serialisables.append(func.__name__)
            print("Adding " + func.__name__)
        return func(self, *args, **kwargs)
    return wrapper
然后在MyClass中初始化序列化文件列表:

class MyClass(object):

    def __init__(self):
        self.serialisables = []

    @property
    @serialise
    def my_prop(self):
        return "this is my property"
使用该属性时,其名称将添加到serialisables属性中:

>>> c = MyClass()
>>> c.my_prop
Adding my_prop
this is my property
>>> c.serialisables
['my_prop']
但是,只有在使用c.my_prop时,才会添加属性的名称:

>>> c = MyClass()
>>> c.serialisables
[]

这正是我所处的位置,也正是我想避免的地方。@othane对不起,我误解了。我认为问题在于“我没有访问类或对象的权限”,调用“self”解决了这个问题。再读一遍后,我发现情况并非如此。这正是我所处的位置,也正是我试图避免的地方。恐怕。@othane我很抱歉我误解了。我认为问题在于“我没有访问类或对象的权限”,调用“self”解决了这个问题。再读一遍,我发现情况并非如此。