2017-02-14 69 views
0

在python中,我需要在我的类,我可能serialize的属性列表,这是麻烦的列出这些在类的顶部。相反,我想用同样的方式@property装饰器使用,这样即东西:蟒蛇装饰添加功能列表上的对象

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__} 

其中__list_of_props_to_serialise__被装饰的对象类时建所以更新我不需要的评论在开始时出线。

问题是,当我编写装饰器时,我无法访问类或对象,除非实际调用my_prop函数,因此我无法添加它。我做错了吗?有没有更好的方法来做到这一点,或者可以做到这一点吗?

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

谢谢。

回答

2

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

因为你在这里property对象,你只能找到的财产​​对象的吸气该属性,所以你需要确保你访问的类型,而不是实例的属性,然后触发单独的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)} 

演示:

​​
+0

awsome的作品就像一个魅力! ...欢呼 – othane

0

你可以写你的装饰类外,有争论的 “自我” 所对应的MyClass的类型的对象:

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 

然后初始化serialisables的列表中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 
[] 
+0

这正是我所在的地方,正是我想要避免的恐惧。 – othane

+0

@othane对不起,我误解了。我认为问题在于“我无法接触到课堂或对象”,这是对“自我”的呼唤所解决的。再次阅读后,我可以看到情况并非如此。 –