Acesso atributo Overridden não funciona (como esperado)
-
18-09-2019 - |
Pergunta
O objetivo principal o módulo seguinte, é fornecer um tipo de semântica "constante" para alguns nomes.
class ConstantError(Exception):
def __init__(self, msg):
self._msg = msg
class Constant(object):
def __init__(self, name):
self._name = name
def __get__(self, instance, owner):
return instance._content[self._name]
def __set__(self, instance, value):
raise ConstantError, 'Illegal use of constant'
class Constants(object):
def __init__(self, content):
self._content = content
for k in self._content:
setattr(self, k, Constant(k))
num_const = Constants({
'one': 1,
'two': 2
})
Quando usado:
>>> from const import *
>>> dir(num_const)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_content', 'one', 'two']
Assim one
e two
estão lá, mas o acesso atributo é diappointing:
>>> num_const.one
<const.Constant object at 0x7faef4871710>
>>>
Onde eu Wold esperar 1
neste caso. Onde eu estou errado?
Solução
O protocolo de descritor só funciona em atributos da classe , e não nos atributos de instâncias de uma classe. Veja a How-To Guide for Descritores
Outras dicas
Está faltando um str () ou unicode () em Constantes.
Adicionar:
def __unicode__(self):
return self._name
Eu penso aulas evita python de acessar as máquinas descritor de modo que eles podem ser manipulados. Caso contrário manipular o descritor poderia ficar muito complicado, sem algum tipo de função 'mágico', e se você tenta python notado para manter um monte de máquinas linguagem acessível. Para contornar esta situação eu sempre gerado a classe na mosca. Por exemplo, você Constantes classe pode ser declarada assim:
class Constants(object):
def __new__(cls, content):
class _Constants(object):
pass
constants = _Constants
constants._content = content
for k in constants._content:
setattr(_Constants, k, Constant(k))
return constants
mas realmente, para você fins que você pode ser melhor com:
class Constants(object):
def __init__(self, content):
self._content = content
def __getattr__(self,key):
return self._content[key]