2015-05-05 2 views
3

В классе "Собака", если я инициализировать, какАргументы функции родительского объекта

self.print_func = print_func 

показано ниже

class Pet(object): 

    def __init__(self, name, print_func): 
     self.name = name 
     self.print_func = print_func 

class Dog(Pet): 

    def __init__(self, name, print_func): 
     Pet.name = name 
     self.print_func = print_func 


    def print_name(self): 
     self.print_func(self.name) 

def print_string(str): 
print str 

когда я

j.print_name() 

все в порядке.

Но если я инициализировать класс собаки, как

Pet.print_func = print_fun 

т.е.

class Dog(Pet): 

     def __init__(self, name, print_func): 
      Pet.name = name 
      Pet.print_func = print_func 


     def print_name(self): 
      self.print_func(self.name) 

когда я

j.print_name() 

Я получаю эту ошибку

TypeError: print_string() takes exactly 1 argument (2 given) 

Итак, почему вызов self.print_func во втором случае передает аргумент «self», но не в первом случае?

ответ

3

Это потому, что в случае self вы создаете так называемую несвязанную функцию, а во втором случае - связанную функцию. Функция Bound эффективно преобразуется в Dog.print_func(self, self.name).

Связанные методы являются немного особенными в том смысле, что они всегда требуют аргумента self, а функции - нет. Они также не существуют в случаях __dict__ - это именно то, что происходит: вы не назначаете его self.__dict__, а Pet.__dict__, поэтому self неявно.

Другими словами, установка Pet.print_func создает метод, а self.print_func создает функцию.

Причина в том, что вы не вызываете Pet конструктор - Pet.print_func изменяет список методов для родителей. Небольшая модификация делает это более ясно:

class Dog(Pet): 

    def __init__(self, name, print_func): 
     Pet.name = name 
     super(Dog, self).print_func = print_func 

Выход

AttributeError: 'super' object has no attribute 'print_func' 

Атрибут (или метод) даже не существует! Но, если конструктор называется ...

class Dog(Pet): 

    def __init__(self, name, print_func): 
     super(Dog, self).__init__(name, print_func) 

Вы снова назначаете функцию. Выход (с указанием имени = 'тест'):

test 

Дальнейшее изучение поведения становится немного более прогностическим. Его можно суммировать следующим образом: если вы добавляете атрибут в класс, он рассматривается как метод. Добавление атрибута в экземпляр оставляет его как функцию (или локальный атрибут).Далее пример

class Dog(Pet): 

    def __init__(self, name, print_func): 
     Pet.name = name 
     super(Dog, self).__dict__['print_func'] = print_func 

Output (имя = 'тест')

test 

надеюсь, объясняет это достаточно хорошо.

Смежные вопросы