Python

2011-01-16 4 views
1

ein Buch liest __getattr__ zu helfen, ich kam in diesem Code ...Python

# module person.py 

class Person: 

    def __init__(self, name, job=None, pay=0): 
     self.name = name 
     self.job = job 
     self.pay = pay 

    def lastName(self): 
     return self.name.split()[-1] 

    def giveRaise(self, percent): 
     self.pay = int(self.pay *(1 + percent)) 

    def __str__(self): 
     return "[Person: %s, %s]" % (self.name,self.pay) 

class Manager(): 
    def __init__(self, name, pay): 
     self.person = Person(name, "mgr", pay) 

    def giveRaise(self, percent, bonus=.10): 
     self.person.giveRaise(percent + bonus) 

    def __getattr__(self, attr): 
     return getattr(self.person, attr) 

    def __str__(self): 
     return str(self.person) 

Es tut, was ich will, zu tun, aber ich verstehe nicht, die __getattr__ Funktion in der Manager Klasse. Ich weiß, dass es alle anderen Attribute von Person Klasse delegiert. aber ich verstehe nicht, wie es funktioniert. zum Beispiel warum von Person Klasse? wie ich es nicht ausdrücklich sage. Person (Modul ist anders als Person (Klasse)

Jede Hilfe sehr geschätzt :)

+2

Mmh entweder der Code ist alt oder schlecht oder ich sehe den Trick dahinter nicht. Aber ich würde nur die 'Manager' Klasse von' Person' erben lassen.Aber ich verstehe deine Frage nicht wirklich. Sie sagen, Sie wissen, was getattr macht. Warum er an "self.person" delegiert: Ich habe diesen Code nicht geschrieben, daher kann ich nur annehmen, dass ein "Manager" eine "Person" ist. Im Konstruktor wird eine neue "Person" erstellt. –

+2

Es ist wirklich alter Code: Es wird nicht von "Objekt" abgeleitet, also sind sie Klassen im alten Stil. Oh, und es ist kaputt: 'Person.lastName' gibt nicht die richtige Antwort für jemanden mit dem Nachnamen" de la Garza "zurück. –

+0

Welches Buch liest du? Das sieht schlecht geschrieben imho ... – ChristopheD

Antwort

0

Eigentlich Sie sie sagen ausdrücklich - nicht durch die Klasse zu benennen, sondern durch eine Instanz dieser Klasse bietet.

In der init-Methode binden Sie self.person an eine Instanz Person. Jetzt hat jede Manager Instanz dieses Datenelement.

In __getattr__ delegieren Sie an das getattr builtin mit self.person als das erste Argument. Unabhängig vom Typ self.person wird nach einem Element mit dem angegebenen Namen gesucht.

+0

Wenn ich ein Manager-Objekt erstelle: m = Manager ("Fred", 1200), warum wird m.person nicht m.person.person bekommen? – Spacedman

2
  1. In Ihrem __init__ Sie instanziieren ein Person Objekt, das zu self.person zugewiesen wird.

  2. Sie dann außer Kraft setzen Attribut-Lookups auf der Manager-Instanz (durch __getattr__ für diese Klasse Implementierung) und leiten diese Attribute stattdessen sah auf der self.person Variable zu (das ist das Person Objekt 1 in diesem speziellen Fall) .

wie Felix Kling in den Kommentaren erwähnt, wäre es sinnvoller, Manager vererben Person zu machen zu machen. Im aktuellen Code oben sieht es aus wie der Manager hat eine Person, während es logisch ist zu denken, dass der Manager eine Person ist.

Man könnte so etwas tun:

class Person(object): 

    def __init__(self, name, job=None, pay=0): 
     self.name = name 
     self.job = job 
     self.pay = pay 

    def give_raise(self, percent): 
     self.pay = int(self.pay *(1 + percent)) 

    def __str__(self): 
     return "[Person: %s, %s]" % (self.name, self.pay) 

class Manager(Person): 

    def __init__(self, name, pay): 
     super(Manager, self).__init__(name, "mgr", pay) 

    def give_raise(self, percent, bonus=.10): 
     self.pay = int(self.pay * (1 + (percent + bonus))) 

# example usage 
John = Person("John", "programmer", 1000) 
Dave = Manager("Dave", 2000) 
print John, Dave 
John.give_raise(.20) 
Dave.give_raise(.20) 
print John, Dave 
0

neben einem Buch zu lesen, möchten Sie vielleicht The Book beraten, wo man eine ziemlich klare Erklärung, wie __getattr__() Methoden funktionieren gefunden haben könnte.

Kurz gesagt, es wird aufgerufen, wenn keine Attribute des angegebenen Namens an das Objekt gebunden sind, auf das es angewendet wird, und auch nicht an die Objektklasse oder eine der Superklassen. Mit anderen Worten, es rief an, wenn alles andere fehlschlägt.

Im Code in Ihrem Beispiel leitet die Implementierung von __getattr_() die Suche nach dem benannten Attribut effektiv auf das Objekt self.person um, das eine Instanz der Klasse Person ist.

Es ist auch wichtig zu verstehen, dass __getattr_() der erste Schritt beim Zugriff auf die Daten und die Methoden für jedes Objekt ist.