[pyar] Duda: @property con __(set|get)attr__
Germán L. Osella Massa
gosella en gmail.com
Jue Feb 14 18:47:19 ART 2013
El día 13 de febrero de 2013 22:35, Claudio Freire
<klaussfreire en gmail.com> escribió:
> 2013/2/13 Germán L. Osella Massa <gosella en gmail.com>:
>> El 13 de febrero de 2013 17:46, Claudio Freire <klaussfreire en gmail.com>
>> escribió:
>>
>>>
>>> No, eso invoca al getter cuando se invoca al setter, lo que puede ser
>>> bastante anti-intuitivo (y dependiendo de lo que haga el setter,
>>> indeseado)
>>
>>
>> Coincido con vos plenamente pero anti-intuitivo y todo, Python es así:
>
>
> No, no es cosa de python, es cosa del código que chequea si tiene el atributo.
Yo me refería a que en Python, cuando usas hasattr(), termina invoca
al getter de la property como efecto secundario no deseado (algo que
desconocía antes de probarlo y hubiera creído que no sucedía...).
Lo de que__setattr__() termina invocando al getter de la property no
tiene excusa (era fácil de implementar así ;-).
> Pero me sigue oliendo mal tener que implementar la lógica esa en
> setattr, y tener que agregar el atributo ese. Justamente una metaclase
> podría "anotar" el setattr automágicamente:
>
>>>> def with_attrs(name, bases, attrs):
> ... attrset = set(attrs)
> ... for base in bases:
> ... attrset.update(set(dir(base)))
> ... attrset = frozenset(attrset)
> ... if attrset and '__setattr__' in attrs and
> callable(attrs['__setattr__']):
> ... _original_setattr = attrs['__setattr__']
> ... def __setattr__(self, name, value):
> ... if name in attrset:
> ... return super(cls, self).__setattr__(name, value)
> ... else:
> ... return _original_setattr(self, name, value)
> ... attrs['__setattr__'] = __setattr__
> ... cls = type(name, bases, attrs)
> ... return cls
> ...
>>>> class pdict(dict):
> ... __metaclass__ = with_attrs
> ... @property
> ... def foo(self):
> ... print("foo.getter")
> ...
> ... @foo.setter
> ... def foo(self, value):
> ... print("foo.setter", value)
> ...
> ... def __getattr__(self, name):
> ... return self.get(name, None)
> ...
> ... def __setattr__(self, name, value):
> ... print("In pdict.__setattr__(self, %r, %r):" % (name, value))
> ...
>>>> d = pdict()
>>>> d.foo
> foo.getter
>>>> d.foo = 3
> ('foo.setter', 3)
>>>> d.bar
>>>> d.bar = 4
> In pdict.__setattr__(self, 'bar', 4):
>
> Listo. Automagia.
Al final, quedó piola usando la metaclase. Con esto, básicamente
__setattr__() implementa una semántica similar a __getattr__(): se
invoca solamente cuando el atributo no existía previamente en el
objeto. Está buena tu solución!
More information about the pyar
mailing list