python __getattr__帮助

时间:2011-01-16 15:26:51

标签: python python-datamodel getattr

读一本书,我遇到了这段代码......

# 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)

它做我想做的事,但我不理解__getattr__类中的Manager函数。我知道它代表Person类的所有其他属性。但我不明白它的工作方式。例如为什么来自Person类?因为我没有明确告诉它。 person(模块与Person(class)不同

非常感谢任何帮助:)

3 个答案:

答案 0 :(得分:2)

  1. __init__中,您实例化了一个Person对象,该对象将被分配给self.person。

  2. 然后覆盖Manager实例上的属性查找(通过为此类实现__getattr__)并重定向这些属性,以便在self.person变量上查找({{1}在这个特殊情况下,来自1的对象)。

  3. 与评论中提到的F​​elix Kling一样,让Person继承自Manager会更有意义。在上面的当前代码中,看起来经理拥有一个人,而认为经理 是一个人更合乎逻辑。

    你可以这样做:

    Person

答案 1 :(得分:0)

实际上,你确实明确告诉它 - 不是通过命名类,而是通过提供该类的实例。

init方法中,您将self.person绑定到Person的实例。现在,每个Manager实例都将拥有此数据成员。

__getattr__中,您将委托getattr内置self.person作为第一个参数。无论self.person的类型如何,它都会查找具有给定名称的成员。

答案 2 :(得分:0)

除了阅读本书之外,您可能还需要咨询The Book,在那里您可以找到__getattr__()方法工作原理的非常明确的解释。

简而言之,当没有指定名称的属性附加到它所应用的对象时,它也会被调用,而不是对象类或它的任何超类。换句话说,它在所有其他方法都失败时调用。

在您的示例中的代码中,__getattr_()的实现有效地将对命名属性的搜索重定向到self.person对象,该对象是Person类的实例。

了解__getattr_()是访问与任何对象相关的数据和方法的第一步也很重要。