Überschrieben Attribut Zugang funktioniert nicht (wie erwartet)
-
18-09-2019 - |
Frage
Das Hauptziel des folgenden Moduls ist eine Art „Konstante“ Semantik für einige Namen zu geben.
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
})
Bei der Verwendung:
>>> 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']
So one
und two
sind da, aber das Attribut Zugriff ist diappointing:
>>> num_const.one
<const.Constant object at 0x7faef4871710>
>>>
Wo ich in diesem Fall erwarten 1
Wold. Wo bin ich falsch?
Lösung
Das Deskriptor-Protokoll funktioniert nur auf Attributen der Klasse , nicht auf Attribute von Instanzen einer Klasse. Sehen Sie sich die How-To Guide für Descriptors
Andere Tipps
Sie vermissen ein str () oder Unicode () -Methode in Constants.
Anzahl:
def __unicode__(self):
return self._name
Ich denke, Python Klassen den Zugriff auf die Beschreiber Maschinen verhindert so, dass sie manipuliert werden können. Andernfalls den Descriptor Manipulation könnte ohne irgendeine Art von ‚magischen‘ Funktion sehr schwierig zu bekommen, und wenn Sie Python versucht habe bemerkt zugänglich viel von der Sprache Maschinen zu halten. Um dies zu umgehen habe ich oft erzeugt die Klasse on the fly. Zum Beispiel könnten Sie Constants Klasse wie so deklariert werden:
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
aber wirklich, für Sie Zwecke könnten Sie besser mit:
class Constants(object):
def __init__(self, content):
self._content = content
def __getattr__(self,key):
return self._content[key]