2017-01-20 4 views
-1

Ich möchte Code bereinigen, die stark eine solche Klasse verwendet:Dict mit objekt wie __getattr__ aber

class ADict(object): 
    pass 
#example usage 
a = ADict() 
a.attr = 1 

Was würde ich die __getattr__ Notation tun wird behalten, aber einen Konstruktor Argument hinzufügen, ist eine Liste der erlaubten ADict Schlüssel, die auch in __getattr__ und __setattr__ überprüft werden. Abgesehen davon, ob es eine gute Idee ist, ist es machbar? Wie? Hier ist meine gescheiterte Versuch (funktioniert nicht wegen unendliche Rekursion):

class ADict(object): 

    def __init__(self, keys): 
    object.__init__(self) 
    self.keys = keys 

    def __getattr__(self, attr): 
    print('hi1') 
    if attr not in object.__getattribute__(self.keys): 
     raise KeyError() 
    return object.__getattr__(self, attr) 

    def __setattr__(self, attr, value): 
    print('hi2') 
    if attr not in object.__getattribute__(self.keys): 
     raise KeyError() 
    return object.__setattr__(self, attr, value) 

a = ADict(['a']) 
a.b = 2 
+0

'wenn attr nicht im Objekt .__ getattribute __ (self.keys):' - warum nicht nur 'wenn attr nicht in self.keys'? Könnten Sie eine [mcve] bereitstellen, die das Traceback enthält? – jonrsharpe

+0

versuchen 'namedtuple'? – shx2

+0

@jonrsharpe: Das Traceback sagt nur, dass ein Rekursionslimit erreicht ist. Ich habe versucht, "self.keys" zu vermeiden, obwohl ich jetzt sehe, dass ich es trotzdem gemacht habe. – d33tah

Antwort

0

Was Sie suchen ist die Schlitze Magie variabel. Grundsätzlich, wenn Sie es definieren Sie die Attribute beschränken, dass ein bestimmtes Objekt haben kann:

class ADict: 
    __slots__ = ['foo', 'bar', 'baz'] 

a = ADict() 
a.foo = 1    # this will work 

a.another_thing = 1 # this will throw an AttributeError 

haben jedoch einen guten Blick auf die Dokumentation, bevor diese Implementierung, da es in der Regel keine gute Idee ist, es sei denn, Sie haben sehr strenge Speicheranforderungen für Ihre Anwendung.

+0

Nur um zu betonen, "__slots__" soll Speicher sparen und hat einige Vorbehalte. Beispielsweise können Sie das allgemeine Idiom einer Klassenvariablen nicht verwenden, um den Instanzvariablen Standardwerte zuzuweisen, wenn die Klasse "__slots__" verwendet. Lesen Sie das Dokument, bevor Sie es verwenden. –

+0

@SergeBallesta: das funktioniert nur in Py2 auf meinem Laptop. – d33tah