2009-10-06 2 views
6

Я использую 'свойство' для того, чтобы изменения переменных экземпляра объектов были обернуты методами, в которых мне нужно.Константные переменные экземпляра?

Как насчет того, когда экземпляр имеет переменную, логически не подлежащую изменению? Например, если я создаю класс для Процесса, каждый экземпляр Процесса должен иметь атрибут pid, который будет часто доступен, но его не следует изменять.

Каков самый Pythonic способ обработать кого-то, пытающегося изменить эту переменную экземпляра?

  • Просто доверять пользователю не пытаться изменить то, что они не должны?

  • Использовать свойство, но вызывать исключение , если переменная экземпляра изменена?

  • Что-то еще?

+0

http://stackoverflow.com/questions/1358711/raising-an-exception-on-updating-a-constant-attribute-in-python –

ответ

6

PREPEND имени переменного с __ и создать свойство только для чтения, Python будет заботиться исключениями, и переменной сам будет защищено от случайной перезаписи.

class foo(object): 
    def __init__(self, bar): 
     self.__bar = bar 

    @property 
    def bar(self): 
     return self.__bar 

f = foo('bar') 
f.bar   # => bar 
f.bar = 'baz' # AttributeError; would have to use f._foo__bar 
+0

В последних двух строках вы имеете в виду «f.foo» и «f .foo = 'baz', верно? –

+0

Да, я перепутал имена переменных. Уже исправлено. –

+1

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

1

Возможно, вы можете оставить __setattr__? В линии,

def __setattr__(self, name, value): 
    if self.__dict__.has_key(name): 
     raise TypeError, 'value is read only' 
    self.__dict__[name] = value 
3

Просто доверять пользователю не обязательно плохо; если вы просто пишете быструю программу Python, которая будет использоваться один раз и выброшена, вы вполне можете просто надеяться, что пользователь не изменит поле pid.

IMHO самый Pythonic способ принудительного использования поля только для чтения - использовать свойство, которое вызывает исключение при попытке установить это поле.

Итак, у ИМХО у вас хорошие инстинкты об этом.

1

Просто используйте свойство и скрытый атрибут (с префиксом подчеркивание).

Простые свойства доступны только для чтения!

>>> class Test (object): 
... @property 
... def bar(self): 
... return self._bar 
... 
>>> t = Test() 
>>> t._bar = 2 
>>> t.bar 
2 
>>> t.bar = 2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: can't set attribute 

Скрытие с двойным подчеркиванием не используется, чтобы скрыть реализацию, но чтобы убедиться, что вы не сталкивались с подклассом атрибутов; рассмотрим, например, смесь, она должна быть очень осторожной!

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