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 ответа

  1. В вашем __init__ вы создаете Person объект, который присваивается self.person.

  2. Затем вы переопределяете поиск атрибутов в экземпляре 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, он будет искать члена с указанным именем.

Другие вопросы по тегам