2017-02-14 16 views
0

В python Мне нужно создать список свойств моего класса, который я могу сериализовать, громоздко отобразить их в верхней части класса. Вместо этого я хотел бы использовать декоратора таким же образом @property используется, то есть что-то вроде этого:python 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__} 

где __list_of_props_to_serialise__ обновляется на объекте с помощью декоратора, когда класс построен таким образом, я не нужно комментируемого в начале.

Проблема заключается в том, когда я прихожу писать декоратор. У меня нет доступа к классу или объекту, пока я фактически не вызову функцию my_prop, поэтому я не могу ее добавить. Я «делаю это неправильно», есть ли лучший способ сделать это, или это можно сделать каким-то образом?

Если это может быть сделано, некоторые могут показать функцию декоратора, которую я могу использовать, иначе, если есть лучший способ, пожалуйста, приведи пример.

Спасибо.

ответ

2

Вместо того, чтобы создавать список, просто добавьте атрибут tagging к объекту функции. Затем перечислите все функции класса, которые имеют этот атрибут.

Потому что у вас есть property объектов здесь, вы можете найти только этот атрибут на поглотителе объекта недвижимости, так что вам нужно, чтобы убедиться, что вы получаете доступ к собственности на типе и не экземпляр, а затем спусковой крючок добытчика отдельно:

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

Демо:

>>> 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)} 
... 
>>> class MyClass(object): 
...  @property 
...  @serialise 
...  def my_prop(self): 
...   return "this is my property" 
... 
>>> serialisables(MyClass()) 
{'my_prop': 'this is my property'} 
+0

awsome работает как шарм !! ... cheers – 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 Извините, я неправильно понял. Я подумал, что проблема связана с тем, что «у меня нет доступа к классу или объекту», который был вызван «я». Прочитав снова, я вижу, что это не так. –