2015-08-12 5 views
1

У меня проблема с определением геттера с использованием @property в конкретном классе. Вот код питона:Определение @property

from abc import ABCMeta, abstractproperty 

class abstract(object): 
    __metaclass__ = ABCMeta 

    def __init__(self, value1): 
     self.v1 = value1 

    @abstractproperty 
    def v1(self): 
     pass 

class concrete(abstract): 
    def __init__(self, value1): 
     super(concrete, self).__init__(value1) 

    @property 
    def v1(self): 
     return self.v1 

Затем проверить код и получаю эту ошибку:

test_concrete = concrete("test1") 
test_concrete.v1 

--------------------------------------------------------------------------- 
AttributeError       Traceback (most recent call last) 
<ipython-input-190-eb896d7ec1c9> in <module>() 
----> 1 test_concrete = concrete("test1") 
     2 test_concrete.v1 

<ipython-input-189-bf15021022d3> in __init__(self, value1) 
    11 class concrete(abstract): 
    12  def __init__(self, value1): 
---> 13   super(concrete, self).__init__(value1) 
    14 
    15  @property 

<ipython-input-189-bf15021022d3> in __init__(self, value1) 
     3 
     4  def __init__(self, value1): 
----> 5   self.v1 = value1 
     6 
     7  @abstractproperty 

AttributeError: can't set attribute 

В основном я намерен установить v1 как атрибут только для чтения.

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

Я нашел обходной путь, используя другое имя для функции геттера v1 в get_v1:

class abstract(object): 
    __metaclass__ = ABCMeta 

    def __init__(self, value1): 
     self.v1 = value1 

    @abstractproperty 
    def get_v1(self): 
     pass 

class concrete(abstract): 
    def __init__(self, value1): 
     super(concrete, self).__init__(value1) 

    @property 
    def get_v1(self): 
     return self.v1 

есть лучший способ решения этой проблемы?

+0

Общепринятая практика - это имена частных атрибутов, таких как '_v1'. – bereal

+0

На самом деле вы не предоставили сеттер для этого объекта, поэтому он доступен только для чтения. Кроме того, вы не можете присвоить атрибуту поддержки то же имя, что и свойство, что не имеет смысла. – jonrsharpe

ответ

2

Ваш вопрос не имеет ничего общего с абстрактными классами. Это проблема с пространством имен; атрибут объекта и атрибуты экземпляра занимают одно и то же пространство имен, вы не можете иметь как атрибут экземпляра, так и свойство использовать одно и то же имя.

Вы пытаетесь получить доступ к свойство с помощью self.v1 = ... и v1 не волшебно атрибутов экземпляра только потому, что вы к нему доступ из метода на экземпляре, который всегда будет объект недвижимости.

В том же ключе, ваша собственность добытчик вызовет бесконечный цикл:

@property 
def v1(self): 
    return self.v1 

потому что self.v1является объект недвижимости, не является атрибутом экземпляра.

Используйте другое имя для фактического хранения:

def __init__(self, value1): 
    self._v1 = value1 

@property 
def v1(self): 
    return self._v1 

Обратите внимание, что вы не можете иметь действительно личные атрибуты в Python (как вы можете в C# или Java); ведущее подчеркивание имен - это только соглашение, и определенный кодер может всегда напрямую обращаться к вашему состоянию экземпляра. Объект property не меняет это.

+0

Спасибо. Он работает, когда я устанавливаю атрибут как _v1. – endeavour90