Ответ 1
Не используйте property
в этом случае. Объект property
- это дескриптор данных, что означает, что любой доступ к instance.var
будет вызывать этот дескриптор, и Python никогда не будет искать атрибут самого экземпляра.
У вас есть два варианта: используйте .__setattr__()
или создайте дескриптор, который реализует только .__set__
.
Использование .__setattr__()
hook
class MyClass(object):
var = 'foo'
def __setattr__(self, name, value):
if name == 'var':
print "Setting var!"
# do something with `value` here, like you would in a
# setter.
value = 'Set to ' + value
super(MyClass, self).__setattr__(name, value)
Теперь обычные чтения атрибутов используются при чтении .var
, но при назначении .var
вместо этого вызывается метод __setattr__
, позволяя вам перехватить value
и отрегулировать его по мере необходимости.
Демо:
>>> mc = MyClass()
>>> mc.var
'foo'
>>> mc.var = 'bar'
Setting var!
>>> mc.var
'Set to bar'
Дескриптор сеттера
Дескриптор сеттера будет только перехватывать присвоение переменной:
class SetterProperty(object):
def __init__(self, func, doc=None):
self.func = func
self.__doc__ = doc if doc is not None else func.__doc__
def __set__(self, obj, value):
return self.func(obj, value)
class Foo(object):
@SetterProperty
def var(self, value):
print 'Setting var!'
self.__dict__['var'] = value
Обратите внимание, как нам нужно назначить атрибуту .__dict__
экземпляра, чтобы предотвратить повторный вызов установщика.
Демо:
>>> f = Foo()
>>> f.var = 'spam'
Setting var!
>>> f.var = 'ham'
Setting var!
>>> f.var
'ham'
>>> f.var = 'biggles'
Setting var!
>>> f.var
'biggles'