2011-06-01 61 views
9

直到像一個小時前,我確信python Foo().bar()只不過是Foo.bar (Foo())的簡寫,它將實例作爲第一個參數傳遞。在這個例子中,最後兩行(顯然)相同的事情:python方法查找,靜態與實例

class Foo (object): 
    def bar (self): print "baz" 

qux = Foo() 
qux.bar() 
Foo.bar (qux) 

但現在我有了一個靜態方法populate()返回人類已知的所有動物的名單一類動物。另外Animal的每個實例都有一個方法populate(),它用隨機值填充實例的屬性。

#! /usr/bin/env python 
# -*- coding: utf-8 -*- 

import random 

animals = [ ("Bella", "cow"), ("Spike", "dog"), ("José", "iguana"), ("Tux", "penguin") ] 

class Animal (object): 
    @staticmethod 
    def populate (*args): return map (lambda x: Animal (*x), animals) 

    def __init__ (self, name = None, species = None): 
     def bar(): self.name, self.species = random.choice (animals) 
     self.name = name 
     self.species = species 
     self.populate = bar 

    def __repr__ (self): return "%s of species %s" % (self.name, self.species) 

print Animal.populate() 
print Animal ("Pinky", "mouse") 
qux = Animal() 
qux.populate() 
print qux 

的代碼工作正常,但是是什麼讓我懷疑的事實是print Animal.populate (qux)稱爲靜態填入方法(因此返回一個列表,並沒有填充qux差)。所以顯然我的信念Foo().bar()無非是Foo.bar (Foo())的簡寫是錯誤的。

這就提出了各種問題,對我來說:

  1. 時會發生什麼我打電話Foo().bar()
  2. 當我撥打Foo.bar (Foo())會發生什麼?
  3. 兩者之間是否存在內在差異?
  4. 我是否缺少python的一些基本概念?
  5. 如果您必須編寫一個類,其靜態填充方法除了通過此類的一個實例調用的填充方法之外還有其他內容,那麼這將是什麼方法?

(是的,它必須是相同的名稱。)

+0

更有趣的標題是「Python方法查找,靜態與實例」。您可以使用該術語獲得更多答案,但技術性更強,更具吸引力。 – slezica 2011-06-01 20:37:39

+0

@Santiago感謝您的意見。我改變了標題。 – Hyperboreus 2011-06-01 20:43:00

+2

'()'周圍的所有額外空間使我的眼睛受傷 – 2011-06-01 21:23:37

回答

2

第一步於foo()之間的差值。如因爲我的答案這是因爲Python(< 3.0)的'綁定'和'非綁定'方法的概念 - 它嚴格要求,除了@staticmethod或@classmethod,方法調用有與他們關聯的實例。沒有什麼更簡單的方法來解釋它,而不僅僅是你必須記住的東西。 謝天謝地,這已經在Python 3中發生了變化 - 作爲單獨的東西的'bound'和'unbound'方法的概念已經消失,並且Foo.bar()對您的示例工作得很好。

+0

太好了。這幫了很多。 – Hyperboreus 2011-06-01 23:43:39

+0

我剛剛從python2.7移動到python3.2,現在我的體驗比以前少了「驚喜」。 – Hyperboreus 2011-06-02 19:53:05

2

靜態方法和類的方法special descriptors。由於描述符的方法參數包括類和任何相關的實例,因此它們可以以任何他們喜歡的方式與方法的參數一起使用。

+0

謝謝。我會閱讀鏈接,最有可能回來更多的問題。 – Hyperboreus 2011-06-01 20:43:41

0

qnx.populate()首先看實例qnxpopulate。如果不存在__mro__,那麼直到找到名爲populate的東西。

Animals.populate(qnx)被巴(),Foo.bar(美孚())和Foo.bar()(跳過在上述查找

+0

非常感謝。我需要一些時間來消化這個。 – Hyperboreus 2011-06-01 21:37:45

+0

有沒有辦法在python中跟蹤MRO? – Hyperboreus 2011-06-01 21:53:48

+0

@Hyperboreus,該類有'__mro__'屬性 – 2011-06-01 21:56:08