python __getattr__ help
Читая книгу, я наткнулся на этот код...
# 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
учебный класс? как я не говорю прямо. человек (модуль отличается от человека (класс)
Любая помощь высоко ценится:)
3 ответа
В вашем
__init__
вы создаетеPerson
объект, который присваивается self.person.Затем вы переопределяете поиск атрибутов в экземпляре Manager (путем реализации
__getattr__
для этого класса) и перенаправить эти атрибуты, чтобы искать вместо этого переменную self.person (которая являетсяPerson
объект из 1 в данном конкретном случае).
Как упоминал Феликс Клинг в комментариях, было бы разумнее Manager
наследовать от Person
, В приведенном выше коде выглядит, что у менеджера есть человек, а логичнее думать, что менеджер - это человек.
Вы могли бы сделать что-то вроде этого:
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
Помимо чтения Книги, вы можете обратиться к Книге, где вы могли бы найти довольно четкое объяснение того, как __getattr__()
методы работы.
В двух словах, он вызывается, когда нет атрибутов с указанным именем, прикрепленных к объекту, к которому он применяется, а также к классу объекта или любому из его суперклассов. Другими словами, он вызывается, когда все остальное терпит неудачу.
В коде в вашем примере реализации __getattr_()
эффективно перенаправляет поиск названного атрибута на self.person
объект, который является экземпляром Person
учебный класс.
Также важно понимать, что __getattr_()
это первый шаг в доступе к данным и методам, связанным с любым объектом.
На самом деле, вы говорите это явно - не путем присвоения имени классу, а путем предоставления экземпляра этого класса.
в init
метод, вы связываете self.person
к примеру Person
, Теперь каждый Manager
Экземпляр будет иметь этот элемент данных.
В __getattr__
Вы делегируете getattr
встроенный с self.person
в качестве первого аргумента. Независимо от типа self.person
, он будет искать члена с указанным именем.