2016-11-25 6 views
-1

Я хочу построить различные сеттеры и геттер. Fot не копировать и вставлять код, я думал что-то решить. Может ли декоратор это сделать?Может ли декоратор обернуть сеттер и геттер в питоне?

@property 
def !!variable_name!!(self): 
    return self.__!!variable_name!! 

@!!variable_name!!.setter 
def !!variable_name!!(self, input): 
    self.__!!variable_name!! = input 

Возможно ли это как макрос в C?

ответ

0

Простой ответ: Да, это возможно с использованием протокола дескриптора. Например, вы хотите сохранить переменные с начальным символом подчеркивания и доступ к ним без подчеркивания такой дескриптор будет работать:

from six import string_types 

class DescriptorSingleLeadingUnderscore(object): 
    def __init__(self, attr, doc=""): 
     if not isinstance(attr, string_types): 
      # Not a string so take the documentation (if avaiable) and name 
      # from the method. 
      if attr.__doc__: 
       doc = attr.__doc__ 
      attr = attr.__name__ 

     self.__doc__ = doc  # Set the documentation of the instance. 
     self.attr = '_' + attr # Add leading underscore to the attribute name 

    def __get__(self, instance, owner=None): 
     if instance is None: 
      return self 
     return getattr(instance, self.attr, None) 

    def __set__(self, instance, value): 
     setattr(instance, self.attr, value) 

    def __delete__(self, instance): 
     delattr(instance, self.attr) 

class X(object): 
    someproperty = DescriptorSingleLeadingUnderscore('someproperty') 
    someproperty1 = DescriptorSingleLeadingUnderscore('someproperty1') 
    someproperty2 = DescriptorSingleLeadingUnderscore('someproperty2') 
    someproperty3 = DescriptorSingleLeadingUnderscore('someproperty3') 

    @DescriptorSingleLeadingUnderscore 
    def it_also_works_as_decorator(self): 
     pass # this code is never executed! 

И тестовый пример:

>>> x = X() 

>>> x.someproperty = 100 
>>> x.someproperty 
100 
>>> x._someproperty 
100 

>>> x.it_also_works_as_decorator = 100 
>>> x.it_also_works_as_decorator 
100 
>>> x._it_also_works_as_decorator 
100 
0

Неясно, почему вы хотели бы сделать что-то подобное создать свойство с сеттер, который игнорирует его значение аргумента, но ответ «Да», вы можете сделать это путем создания функции, которая возвращает обычай property объекта:

Однако вы не можете использовать синтаксис @ для его применения. Вместо этого вы должны использовать его, как показано ниже:

def attribute_property(name, input_value): 
    STORAGE_NAME = '_' + name 

    @property 
    def prop(self): 
     return getattr(self, STORAGE_NAME) 

    @prop.setter 
    def prop(self, ignored): 
     setattr(self, STORAGE_NAME, input_value) 

    return prop 

# EXAMPLE USAGE 
class Person(object): 
    name = attribute_property('name', 'Monty') 

    def __init__(self, name, age): 
     self.name = name # ignores value of passed "name" argument! 
     self.age = age 

user = Person('Rodrigo', 42) 
print('user.name: {!r}'.format(user.name)) 
print('user.age: {!r}'.format(user.age)) 

Выход:

user.name: 'Monty' 
user.age: 42 
+1

Minor опечатка: 'self.name - name' должен быть' self.name = name', верно? – MSeifert