2012-03-13 71 views
2

正如人們所熟悉的絕大多數人,這是來自Mark Pilgrim的書DIP,第5章理解蟒蛇自我和init

class FileInfo(UserDict): 
    "store file metadata" 
    def __init__(self, filename=None): 
     UserDict.__init__(self) 
     self["name"] = filename 

嗯,我是新來的蟒蛇,從基本的C背景的,並具有混淆理解它。在我不明白之前說明我的理解。

聲明0:FileInfoUserDict

聲明1繼承:__init__不是構造,類實例化後然而,這是第一方法定義了。

聲明2:self幾乎是像this

現在麻煩:每St1的INIT 作爲被定義爲所述第一函數。

UserDict.__init__(self) 

現在爲什麼被引用的函數相同的功能__init__內,沒有內在的遞歸我猜。或者它試圖覆蓋類的__init__方法,該類FileInfo已經繼承並放置了一個額外的文件名參數(鍵值對)並將其引用到傳遞給__init__方法的文件名。

我部分地確定,我已經回答了我的問題,但是因爲您可以感覺到存在混淆,如果有人能夠解釋我如何用一些更高級的用例和一般的詳細示例來解釋這種混淆代碼被寫入。

回答

4

你是對的,__init__方法不是構造函數,它是在實例化對象後調用的初始化方法。

在你提供的代碼,在FileInfo__init__方法擴展的基類,UserDict__init__方法的功能。通過調用基類__init__方法,它會執行基類初始化中的任何代碼,然後添加它自己的代碼。如果沒有調用基類的__init__方法,則只會調用明確添加到FileInfo的方法中的代碼。

傳統的做法是使用super方法。

class FileInfo(UserDict): 
    "store file metadata" 
    def __init__(self, filename=None): 
     super(UserDict, self).__init__() 
     self["name"] = filename 

一個常見的用例是返回額外的值或添加額外的功能。在Django基於類的視圖中,方法get_context_data用於獲取用於呈現模板的數據字典。因此,在擴展方法中,您將獲得基本方法返回的任何值,然後添加自己的值。

class MyView(TemplateView): 
    def get_context_data(self, **kwargs): 
     context = super(MyClass, self).get_context_data(**kwargs) 
     context['new_key'] = self.some_custom_method() 
     return kwargs 

這樣,當你想擴展它時,你不需要重新實現基方法的功能。

0

__init__不是構造函數,但是在類實例化之後,這是第一個定義的方法。

當一個實例被初始化該方法被調用時,後__new__(即,當調用ClassName())。我不確定與構造函數相比有什麼區別。

聲明2:自我是差不多是這樣

是的,但它不是一個語言結構。名稱self只是慣例。傳遞給實例方法的第一個參數始終是對類實例本身的引用,因此在此處寫自己只是爲其命名(將其分配給變量)。

的UserDict .__的init __(個體經營)

在這裏,您所呼叫的UserDict中的__init__方法,並把它引用到新的實例(因爲你不self.method_name調用它,它是不會自動傳遞。不能在不引用其名稱的情況下調用繼承類的構造函數,或使用super)。所以你正在做的是以與初始化任何UserDict對象相同的方式初始化你的對象。「

0

」或者它試圖覆蓋類FileInfo已繼承的類UserDict的init方法,並將文件名的額外參數(鍵值對)並將其引用到傳遞給init方法的文件名中。

就是這樣。 UserDict.__init__(self)調用超類init方法。因爲你來自C,也許你對OOP並不熟悉,所以你可以閱讀這篇文章:http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)以更好地理解繼承原則(以及我使用的「超類」術語)。

0

當您爲繼承自基類的類調用__init__方法時,通常會修改祖先類並作爲自定義的一部分,可以使用適當的參數來擴展祖先的init方法。

0

FileInfo的__init__方法覆蓋了UserDict__init__方法。

然後FileInfo.__init__在新創建的FileInfo實例(self)上調用UserDict.__init__。通過這種方式,UserDict可用的所有屬性和魔法現在可用於FileInfo實例(即它們從UserDict繼承)。

最後一行是覆蓋的原因UserDict.__init__:UserDict不會創建想要的屬性self.filename

0

..自變量表示對象本身的實例。在Python中,這不像其他語言中的隱藏參數。你必須明確地聲明它。當您創建FileInfo類的實例並調用其方法時,它將自動傳遞,

__init__方法大致上代表了Python中的構造函數。

4

在Python中創建一個對象是一個過程分爲兩個步驟:

  • __new__(self, ...)#構造函數

  • __init__(self, ...)#初始化

__new__具有創建對象的責任,主要用於當對象被認爲是不可變的時候。

__init____new__之後被調用,並且需要進一步的配置。由於Python中的大多數對象都是可變的,因此通常會跳過__new__

self涉及所述對象。例如,如果您有d = dict(); d.keys(),則在keys方法self將參考d而不是dict

當一個子類有一個與其父類相同名稱的方法時,Python調用子類的方法並忽略父類;所以如果父類的方法需要被調用,那麼子類方法必須調用它。

+0

在類中定義'__new__'的情況很少見。我只寫過一次'Singleton'類裝飾器。 – wberry 2012-03-13 16:08:39

+0

的確 - 這就是爲什麼我說它通常被跳過。 – 2012-03-13 16:15:11