2015-05-05 99 views
3

在 「狗」 類,如果我初始化如下圖所示參數給對象的父的功能

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 

self.print_func = print_func 

當我做

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的情況下,您正在創建所謂的未綁定函數,而在第二種情況下是綁定函數。綁定函數有效轉換爲Dog.print_func(self, self.name)

綁定方法有點特殊,因爲它們總是需要自我參數,而函數不需要。在__dict__的情況下它們也不存在 - 這正是發生的情況:您不是將它分配給self.__dict__,而是分配給Pet.__dict__,因此由Python隱式地分配給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 

輸出(給定名稱= '測試')

test 

希望解釋它不夠好。