2016-04-03 10 views
0

nehme ich eine GUI baue die Attribute einer Sammlung von Building Objekte zu ändern:Wörterbuch Tasten Klasse zuzugreifen Attribute

class Building: 

    def __init__(self, company, addr): 
     self.company = company 
     self.addr = addr 

Jedes Mal, wenn ein neues Building in der GUI markiert ist, sollten verschiedene Widgets zu aktualisieren, um spiegeln die Attribute dieses Objekts wider.

Ich möchte jedes Building-Attribut mit dem Widget verknüpfen, das es steuert. Vielleicht etwas in dieser Richtung:

attribute_widget_map = { 
    'company': company_widget, 
    'addr': addr:widget, 
} 

so dass, wenn ich gehen, um den Wert jedes Widget zu setzen, ich es wie folgt tun:

building = Building('XYZ', 'Anytown USA') 
for attr, widget in attribute_widget_map.items(): 
    widget.set_value(building.__getattr__(attr)) 

Mein Problem mit diesem: Ich mag das nicht Die Schlüssel in attribute_widget_map sind String-Darstellungen von Building Eigenschaften. Angenommen, ich ändere addr zu address. Der Code wird unterbrochen. Gibt es einen anderen Weg dies zu tun als sich auf __getattr__ zu verlassen?

Was sind die Alternativen?

+0

So oder so, wenn Sie einen ändern, müssen Sie den anderen ändern. Nein? – idjaw

+0

vielleicht hätte meine Frage sein sollen: Ist das eine angemessene Verwendung von '__getattr__'? – Crispin

+0

Das scheint mir gut. Zugegeben, vielleicht könnte jemand mitkommen und etwas anderes zu sagen haben. Aber sieht gut zu mir aus. – idjaw

Antwort

0

Sie könnten wahrscheinlich lösen diese mit einer Variante des property Dekorateur:

class Bindings: 
    def __init__(self): 
     self.__bindings = [] 
    def bound_to(self, widget): 
     def inner(func): 
      prop = property(func) 
      self.__bindings.append((prop, widget)) 
      return prop 
     return inner 
    def __iter__(self): 
     return iter(self.__bindings) 

class Building: 
    def __init__(self, address): 
     self._address = address 

    bindings = Bindings() 

    @bindings.bound_to("address_widget") 
    def address(self): 
     return self._address 

    @address.setter 
    def address(self, value): 
     self._address = value 

Dann können Sie eine Funktion haben:

def update_widgets(building): 
    for prop, widget in building.bindings: 
     widget.value = prop.fget(building) 

Verwendung des folgenden Widget-Stub:

>>> class Widget: 
...  def __init__(self, name): 
...   self.name = name 
...   Bindings.boundWidget['address'] = self 
...  def update(self, value): 
...   print(self.name, value) 
... 

-

>>> address_widget = Widget("Address widget") 
>>> anySt = Building("123 Any Street") 
>>> someAv = Building("42 Some Avenue") 
>>>  
>>> update_widgets(anySt) 
Address widget 123 Any Street 
>>> update_widgets(someAv) 
Address widget 42 Some Avenue 
Verwandte Themen