attributi di accesso ignorato non funziona (come previsto)
-
18-09-2019 - |
Domanda
L'obiettivo principale del modulo successivo, è quello di fornire una sorta di semantica "costante" per alcuni nomi.
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 viene utilizzato:
>>> 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']
Così one
e two
ci sono, ma l'accesso agli attributi è diappointing:
>>> num_const.one
<const.Constant object at 0x7faef4871710>
>>>
Dove ho wold aspettare 1
in questo caso. Dove mi sbaglio?
Soluzione
Il protocollo descrittore funziona solo su attributi della classe , non sugli attributi di istanze di una classe. Vedere la Guida alle procedure per descrittori
Altri suggerimenti
Ti manca un str () o unicode () metodo Costanti.
Add:
def __unicode__(self):
return self._name
Credo Python impedisce classi di accedere alla macchina descrittore in modo che possano essere manipolati. In caso contrario, manipolando il descrittore potrebbe diventare molto difficile senza un qualche tipo di funzione 'magico', e se avete notato cerca pitone per mantenere un sacco di macchine linguaggio accessibile. Per ovviare a questo ho spesso generato la classe al volo. Ad esempio, classe che si Costanti potrebbe essere dichiarato in questo modo:
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
, ma in realtà, per voi scopi potrebbe essere meglio di con:
class Constants(object):
def __init__(self, content):
self._content = content
def __getattr__(self,key):
return self._content[key]