2016-02-13 43 views
0

我在練習基本的python腳本時從網站上找到了下面的代碼。從下面的代碼中,我能夠理解類和實例以及第一個打印語句。Python簡單的類理解

但我不明白在第二個和第三個打印語句後面使用的概念。如何將實例(在下面的代碼polly中)作爲參數傳遞給類的方法? Python中有沒有任何選項可以像這樣傳遞?

class Pet(object): 

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

    def getName(self): 
     return self.name 

    def getSpecies(self): 
     return self.species 

    def __str__(self): 
     return "%s is a %s" % (self.name, self.species) 

polly = Pet("Polly", "Parrot") 

print "Polly is a %s" % polly.getSpecies() 
Polly is a Parrot 

print "Polly is a %s" % Pet.getSpecies(polly) 
Polly is a Parrot 

print "Polly is a %s" % Pet.getSpecies() 
Traceback (most recent call last): 
    File "", line 1, in 
    TypeError: unbound method getSpecies() must be called with Pet instance as first argument (got nothing instead) 
+0

極短:看'self'。在第一種情況下,'self'作爲第一個參數被隱式發送到'getSpecies',因爲在實例上調用了getSpecies。在這種情況下,'self'是'Pet'的一個實例,即'polly'。在第二種情況下,'self'作爲getSpecies的參數顯式給出,因爲該方法不在實例上調用,而是在類上調用。而那個「自我」論證恰好是「polly」。 – Evert

+0

有問題的代碼是Python 2特有的,第3條語句的行爲在Python 3中稍有改變;沒有要求使用Pet實例專門調用未綁定的方法。 –

回答

1

實際上,instance.instance_method()在內部會變成TheClass.instance_method(instance)self是指實例本身。所以第一個和第二個版本是相等的。

一個簡單的例子:

def getSpeciesGlobal(some_object): # a normal function 
    return some_object.species 

polly = Pet("Polly", "Parrot") 
polly.species # "Parrot" 
getSpeciesGlobal(polly) # "Parrot" 
# if we assign this function to the class. 
Pet.getSpeciesGlobal = getSpeciesGlobal 
Pet.getSpeciesGlobal(polly) # "Parrot" 

# the original way in your question 
polly.getSpecies() # "Parrot" 
Pet.getSpecies(polly) # "Parrot" 
0

在第二個打印語句中,polly作爲自變量傳遞給類方法。這在第一次印刷聲明中隱含發生。 在第三次打印中,類方法被調用,但沒有實際的數據要處理的對象。

1

在Python中,一個類可以被視爲一包屬性。請看下圖:

>>> class Stuff: 
...  pi = 3.14 
...  def foo(x, y): 
...   return x + y 
...  bar = lambda s: s * 2 
... 
>>> Stuff.bar(4) 
8 
>>> Stuff.foo(5,6) 
11 
>>> Stuff.pi 
3.14 

在這個例子中,Stuff只是一堆隨機的對象。所以Stuff.bar是指實際功能bar。類的實例具有不同的行爲:訪問函數時,它會自動轉換爲綁定方法。這意味着該實例會自動作爲第一個參數傳遞。

當您撥打Pet.getSpecies(polly)時,polly將作爲self參數傳入。 self沒有什麼魔力,它只是另一個參數。當你訪問polly.getSpecies並獲得<bound method Polly.getSpecies of <__main__.Polly object at 0x7f946cd14b38>而不是<function Polly.getSpecies at 0x7f946cd1e048>時,這種魔法就是。

還有@classmethod裝飾器,它接收類作爲第一個參數而不是實例,並且通過清晰地定界類方法和實例方法使得代碼更容易理解。