2014-09-23 10 views
7

Obecnie, kiedy chcemy zdefiniować setter i getter zostawić sam mogę to zrobić:Definiowanie setter w krótszej drodze

@property 
def my_property(self): 
    return self._my_property 

@my_property.setter 
def my_property(self, value): 
    value.do_some_magic() 
    self._my_property = value 

Czy jest jakiś sposób, aby krótsza? Chciałbym pominąć tę część, ponieważ zawsze wyglądają tak samo:

@property 
def my_property(self): 
    return self._my_property 
+2

W języku Python zawsze jest krótsza droga. Myślę, że można osiągnąć coś takiego za pomocą metaklasy, ale nie sądzę, że byłoby to warte złożoności lub odchylenia od standardowego kodu. –

Odpowiedz

5

Można zrobić dekorator, który automatycznie tworzy getter, następującą konwencją podkreślenia:

def setter(fn): 
    def _get(self): 
     return getattr(self, '_' + fn.__name__) 
    def _set(self, val): 
     return fn(self, val) 
    return property(_get, _set) 

lub bardziej zwięźle, jeśli lubisz tego stylu więcej:

def setter(fn): 
    return property(
     lambda self: getattr(self, '_' + fn.__name__), 
     fn) 

Zastosowanie:

class X(object): 
    @setter 
    def my_property(self, value): 
     self._my_property = value + 1 

x = X() 
x.my_property = 42 
print x.my_property # 43 
1

nie ma skrótu, że znam of- pamiętać wyraźny jest lepszy niż niejawny (od Zen Pythona).

Może to być tak, że w twoim kodzie do tej pory właściwość jest zawsze taka - ale możesz w pewnym momencie napisać właściwość getter, która pobiera całkowicie wyliczoną wartość - w takim przypadku twój getter nieruchomości i seter nie będą tak wyglądać w ogóle.

Powiedział, że można napisać opakowanie, które zapewnia te proste domyślne metody jako część opakowania, jeśli chcesz.

1
def set_my_property(self, value): 
    value.do_some_magic() 
    self._my_property = value 

my_property = property(fset=set_my_property) 
6

Nie ma się z roztworu skrzynki, ale można spróbować czegoś takiego:

def defprop(name): 
    def getter(self): 
     return getattr(self, name) 
    return property(getter) 

class C(object): 
    # ... 
    my_dictionary = defprop('_my_dictionary') 
    # ... 

Że cię nie zapisać, że wiele klawiszy choć nadal trzeba powielać nazwę atrybutu. Poza tym jest mniej wyraźny.


Aktualizacja: po przemyśleniu trochę, mam wymyślić tego deskryptora oparte hackish sztuczki (disclaimer: odbywa się to tylko na pokaz, nie oznacza, że ​​jest to dobra praktyka, chyba że mieć cholernie dobry powód, aby to zrobić):

class with_default_getter(object): 
    def __init__(self, func): 
     self._attr_name = '_{0.__name__}'.format(func) 
     self._setter = func 

    def __get__(self, obj, type): 
     return getattr(obj, self._attr_name) 

    def __set__(self, obj, value): 
     return self._setter(obj, value) 

Zastosowanie:

class C(object): 
    @with_default_getter 
    def my_property(self, value): 
     print 'setting %s' 
     self._my_property = value 

>>> c = C() 
>>> c.my_property = 123 
setting 123 
>>> c.my_property 
123 

jest niemal tak samo jak @georg sugeruje, tylko rozkłada wyko mentacja do deskryptorów.