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?

War es hilfreich?

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]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top