读一本书,我遇到了这段代码......
# 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)不同
非常感谢任何帮助:)
答案 0 :(得分:2)
在__init__
中,您实例化了一个Person
对象,该对象将被分配给self.person。
然后覆盖Manager实例上的属性查找(通过为此类实现__getattr__
)并重定向这些属性,以便在self.person变量上查找({{1}在这个特殊情况下,来自1的对象)。
与评论中提到的Felix 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_()
是访问与任何对象相关的数据和方法的第一步也很重要。