2009-08-06 11 views
5

die folgende Klasse vor:Controlling Getter und Setter für eine Klasse der Python

class Token: 
    def __init__(self): 
     self.d_dict = {} 

    def __setattr__(self, s_name, value): 
     self.d_dict[s_name] = value 

    def __getattr__(self, s_name): 
     if s_name in self.d_dict.keys(): 
      return self.d_dict[s_name] 
     else: 
      raise AttributeError('No attribute {0} found !'.format(s_name)) 

In meinem Code Token haben eine andere Funktion (wie get_all() wich Rückkehr d_dict hat (s_name), die mir sagen, ob mein Token hat ein bestimmtes Attribut).

Wie auch immer, ich denke, das ist ein Fehler in meinem Plan, da es nicht funktioniert: Wenn ich eine neue Instanz erstellen, versuchen Python __setattr__('d_dict', '{}') aufrufen.

Wie kann ich ein ähnliches Verhalten (vielleicht in einer mehr pythischen Weise?) Erreichen, ohne etwas wie Token.set (Name, Wert) und get (Name) zu schreiben, die ich setzen oder ein Attribut für ein erhalten möchte Zeichen.

Kritiker über Designfehler und/oder Dummheit willkommen :)

danken!

Antwort

3

Sie müssen Sonderfall d_dict.

Obwohl natürlich, in dem obigen Code, alles, was Sie tun, replizieren, was jedes Objekt mit __dict__ bereits tut, so ist es ziemlich sinnlos. Schätze ich richtig, wenn Sie bestimmte Attribute speziell verwenden und Methoden dafür verwenden möchten?

In diesem Fall können Sie Eigenschaften verwenden.

class C(object): 
    def __init__(self): 
     self._x = None 

    @property 
    def x(self): 
     """I'm the 'x' property.""" 
     return self._x 

    @x.setter 
    def x(self, value): 
     self._x = value 

    @x.deleter 
    def x(self): 
     del self._x 
1

Eine Lösung, nicht sehr Python aber funktioniert. Wie Lennart Regebro sagte, müssen Sie einen speziellen Fall für d_dict verwenden.

class Token(object): 

    def __init__(self): 
     super(Token,self).__setattr__('d_dict', {}) 

    def __getattr__(self,name): 
     return self.a[name] 

    def __setattr__(self,name,value): 
     self.a[name] = value 

Sie müssen neue Stilklassen verwenden.

1

Es wird daran erinnert, dass __getattr__ nur aufgerufen wird, wenn das Attribut nicht im Objekt vorhanden ist, während __setattr__ immer aufgerufen wird.

3

Die Spezialgehäuse __dict__ funktioniert wie folgt:

def __init__(self): 
    self.__dict__['d_dict'] = {} 

Es besteht keine Notwendigkeit, einen neuen Stil-Klasse für das verwenden.

+0

Ich denke, ich werde das tun :) Wie auch immer, ich benutze Python 3.1 so alle meine Klasse sind neue Stilklasse. – thomas

2

das Problem scheint in der Zeit der Auswertung Ihres Codes in __init__ Methode zu sein. Sie könnten __new__ method definieren und dort d_dict Variable statt __init__ initialisieren. Das ist ein bisschen hackish, aber es funktioniert, erinnere dich daran, es zu kommentieren, wie nach wenigen Monaten wird es totale Magie sein.

>>> class Foo(object): 
...  def __new__(cls, *args): 
...    my_cls = super(Foo, cls).__new__(cls, *args) 
...    my_cls.d_dict = {} 
...    return my_cls 

>>> f = Foo() 
>>> id(f.d_dict) 
3077948796L 
>>> d = Foo() 
>>> id(d.d_dict) 
3078142804L 

Wort der Erklärung, warum ich die Meinung, dass hackish: Aufruf gibt neue Instanz von Klasse __new__ so dann d_dict initialisiert dort ist eine Art statischen, aber es wird mit neuer Instanz Wörterbuch initialisiert jede Zeitklasse ist "erstellt" so funktioniert alles wie Sie brauchen.

0

Ich denke, wir können etwas über das Gesamtdesign Ihrer Klasse sagen, wenn Sie ihren Zweck erklären.Zum Beispiel

# This is a class that serves as a dictionary but also has user-defined methods 
class mydict(dict): pass 

# This is a class that allows setting x.attr = value or getting x.attr: 
class mysetget: pass 

# This is a class that allows setting x.attr = value or getting x.attr: 
class mygetsethas: 
    def has(self, key): 
     return key in self.__dict__ 

x = mygetsethas() 
x.a = 5 
print(x.has('a'), x.a) 

Ich denke, die letzte Klasse am nächsten ist, was Sie meinten, und Ich mag auch mit Syntax und bekommen viel Freude aus, es zu spielen, aber das ist leider nicht eine gute Sache. Gründe, warum es nicht ratsam ist, Objektattribute zu verwenden, um Wörterbuch wieder zu implementieren: Sie können x.3 nicht verwenden, Konflikt mit x.has(), Sie müssen Zitate in has('a') und viele mehr setzen.

+0

Mein Ziel ist es, einen Behälter bereitzustellen, der mir erlauben es, jede beliebige Attribut zu geben (ich weiß nicht im Voraus, wie viele noch ihren Namen), zB: myClassInstance.name1 = value1 myClassInstance.name2 = value2 Mit dem entsprechenden Ich möchte ein Wörterbuch abrufen, das den Namen und den Wert meiner Attribute unter dem folgenden Formular enthält: {'Name1': Wert1, 'Name2': Wert2} ValueX kann beliebiger Python oder benutzerdefinierten Typ sein. – thomas

+0

Dann ist dein bestes das zweite, 'class mysetget: pass'. Sie können Attribute festlegen und sie dann mit "x .__ dict__" abrufen. –