Zunächst ist es fast immer eine schlechte Idee, so etwas zu tun. Wenn nur der Grund, warum Sie wollen, dass Sie sicherstellen, dass Sie keine Tippfehler machen - es gibt bessere Werkzeuge dafür (glaube IDE oder pylint). Wenn Sie 100% positiv sind, dass Sie so etwas brauchen, sind hier zwei Möglichkeiten:
Erste Möglichkeit - Sie können dies mit der Verwendung __setattr__
Methode tun. Siehe python __setattr__
documentation
class Person(object):
def __init__(self, first_name, last_name):
self.__dict__['first_name'] = first_name
self.__dict__['last_name'] = last_name
def __setattr__(self, name, value):
if name in self.__dict__:
super(Person, self).__setattr__(name, value)
else:
raise AttributeError("%s has no attribute %s" %(self.__class__.__name__, name))
und Ausgang:
In [49]: a = Person(1, 2)
In [50]: a.a = 2
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 a.a = 2
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in __setattr__(self, name, value)
8 super(Person, self).__setattr__(name, value)
9 else:
---> 10 raise AttributeError("%s has no attribute %s" %(self.__class__.__name__, name))
AttributeError: Person has no attribute a
Alternativ können Sie tun dies mit __slots__
(python __slots__
documentation):
class Person(object):
__slots__ = ("first_name", "last_name")
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
Ausgang:
In [32]: a = Person("a", "b")
In [33]: a.first_name
Out[33]: 'a'
In [34]: a.a = 1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 a.a = 1
AttributeError: 'Person' object has no attribute 'a'
Der erste Weg ist flexibler, da er es ermöglicht, diesen Code durch die direkte Verwendung von __dict__
noch weiter zu hacken, aber das wäre noch mehr falsch als jetzt. Der zweite Ansatz reserviert den Platz für eine bestimmte Anzahl von Instanzvariablen (Referenzen), was weniger Speicherverbrauch bedeutet.
Ich denke, das ist ein Beispiel dafür, was man "Affenflicken" nennt, und ich denke, es ist eines der Dinge, die die Leute an Python lieben. Es klingt also ein bisschen wie du mit der Sprache kämpfst. – BenDundee
Wenn Sie wirklich müssen, kann '__slots__' erreichen, was Sie tun möchten. Jedoch sollte es wirklich nicht dafür verwendet werden ... Ich würde das "__slots__" missbrauchen. Letztendlich ist dies der Grund, warum Sie eine konsistente API und eine gute Dokumentation bereitstellen müssen. Wenn ein Benutzer einen Fehler erhält, stellt er fest, dass er Ihre API nicht korrekt verwendet hat. – mgilson
@BenDundee: Beim Monkeypatching geht es hauptsächlich um das Hinzufügen/Ändern von Verhalten zur Laufzeit. Wenn Sie sich auf die gleichen Mechanismen verlassen, ist das obige Beispiel definitiv ein Tippfehler, kein Monkeypatch;) –