溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中self的四個(gè)秘密分別是什么

發(fā)布時(shí)間:2021-10-11 18:31:01 來源:億速云 閱讀:127 作者:柒染 欄目:web開發(fā)

這篇文章給大家介紹Python中self的四個(gè)秘密分別是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

self的謎團(tuán)

毫無疑問,幾乎每一門Python課程都有一個(gè)關(guān)于(class)類的講座——面向?qū)ο缶幊陶Z言的基本構(gòu)建模塊之一。

當(dāng)您通過一些示例學(xué)習(xí)它時(shí),您將注意到在Python類中定義的許多函數(shù)都將self作為它們的第一個(gè)參數(shù)。例如,在下面的代碼片段中,我們聲明了一個(gè)名為Student的類,它的greet()方法的第一個(gè)參數(shù)是self。但是,函數(shù)根本沒有使用self,所以這里的self到底是從哪里來的呢?這對許多初學(xué)者來說是第一個(gè)謎。

>>> class Student: ...     def greet(self, name): ...         print('Good Morning, ' + name) ...  >>> student = Student() >>> student.greet('John') Good Morning, John

同樣奇怪的是,當(dāng)我們使用這個(gè)函數(shù)時(shí),我們并沒有給self參數(shù)設(shè)置任何東西,這是困擾我們的另一個(gè)謎題。在這篇文章中,我們將與學(xué)習(xí)者分享一些Python中self的奧秘。

Python中self的四個(gè)秘密分別是什么

1. 它代表什么?

在開始處理這個(gè)謎題之前,我們需要理解兩個(gè)基本的相關(guān)概念:類和實(shí)例。當(dāng)然,解決所有這些謎題需要額外的知識,而不僅僅是類和實(shí)例,我將在接下來的討論中澄清這一點(diǎn)。如果你對這兩個(gè)概念都很了解,你可以跳過下一段,這段只是對這兩個(gè)概念的簡要概述。

創(chuàng)建Python類就是聲明一種新的對象類型,它提供了一種將數(shù)據(jù)和功能捆綁在一起的機(jī)制。在上面的示例中,我們創(chuàng)建了一個(gè)名為Student的類,并使用它創(chuàng)建了一個(gè)名為Student的學(xué)生類型的對象。這個(gè)對象被稱為student類的實(shí)例。此外,類還可以提供通常稱為屬性的特定功能,例如示例中的greet()函數(shù)。我們使用三個(gè)內(nèi)省(introspection)函數(shù)(type()、isinstance()和hasattr())來檢查相關(guān)信息。

>>> type(Student) <class 'type'> >>> type(student) <class '__main__.Student'> >>> isinstance(student, Student) True >>> hasattr(Student, 'greet') True

我可以簡單地告訴您,greet()函數(shù)中的self參數(shù)是上面示例中的student實(shí)例。更一般地說,是實(shí)例調(diào)用這個(gè)函數(shù)。以下是支持證據(jù):

>>> class Student: ...     def greet(self, name): ...         print(id(self)) ...         print('Good Morning, ' + name) ...  >>> student = Student() >>> student.greet('John') 4546580944 Good Morning, John >>> id(student) 4546580944

在上面的代碼中,我們修改了greet()函數(shù),要求它使用內(nèi)省id()函數(shù)向我們顯示self參數(shù)的內(nèi)存地址。如您所見,self參數(shù)和實(shí)例student是同一個(gè)對象,因?yàn)樗鼈兙哂邢嗤膬?nèi)存地址。

Python中self的四個(gè)秘密分別是什么

2. 為什么不需要在函數(shù)調(diào)用中設(shè)置它呢?

繼續(xù)上一節(jié)中展示的示例,當(dāng)我們使用實(shí)例student調(diào)用greet()函數(shù)時(shí),這個(gè)函數(shù)通常被稱為實(shí)例方法&mdash;&mdash;一個(gè)對某個(gè)類的實(shí)例可用的函數(shù)。但是,如果我們檢查這個(gè)屬性的類型,就會顯示一些不同的東西。

>>> student = Student() >>> student.greet <bound method Student.greet of <__main__.Student object at 0x10eff5750>>

如上所述,實(shí)例student的greet屬性稱為綁定方法。具體來說,它被綁定到Student類的greet屬性。

為了準(zhǔn)確理解這意味著什么,讓我們看看下面的代碼:

>>> Student.greet(student, 'John') Good Morning, John

結(jié)合開頭的示例,您可能會注意到這段代碼中的三件事:

  1. 這個(gè)函數(shù)的調(diào)用者是類Student,而不是實(shí)例student。

  2. 在這個(gè)調(diào)用中設(shè)置了self和name參數(shù),這與student調(diào)用初始函數(shù)時(shí)忽略self參數(shù)不同。

  3. 兩個(gè)函數(shù)調(diào)用都產(chǎn)生了相同的輸出。它們本質(zhì)上用的是同一個(gè)函數(shù)。

通過實(shí)現(xiàn)這些信息,您可能已經(jīng)猜到在使用實(shí)例student調(diào)用greet()函數(shù)時(shí),幕后發(fā)生了什么。

Python中self的四個(gè)秘密分別是什么

如上圖所示,當(dāng)實(shí)例student調(diào)用greet(' John ')方法時(shí),解釋器將處理此函數(shù)調(diào)用,作為類Student將調(diào)用者(即實(shí)例student)和name參數(shù)(即' John ')發(fā)送給greet(self, name)函數(shù),該函數(shù)打印“Good Morning, John”。

對于感興趣的讀者,這里有幾件事要知道,可以幫助你更深入地了解這個(gè)謎。當(dāng)創(chuàng)建一個(gè)Python類時(shí),它聲明的函數(shù)就是這個(gè)類的屬性(稱為函數(shù)對象)。換句話說,類“擁有”這些函數(shù)。類的實(shí)例不會直接實(shí)現(xiàn)這些函數(shù)。相反,它們將具有與類中實(shí)現(xiàn)的相應(yīng)函數(shù)綁定的相同屬性(即實(shí)例方法)。

3.self是一個(gè)關(guān)鍵詞嗎?

似乎在所有這些已定義的函數(shù)中,我們都使用self作為它們的第一個(gè)參數(shù)。有些人可能錯(cuò)誤地認(rèn)為self是Python為這些用例保留的關(guān)鍵字。然而,事實(shí)并非如此。請看下面一個(gè)簡單的例子:

>>> def=5   File "<stdin>", line 1     def=5        ^ SyntaxError: invalid syntax >>> class=4   File "<stdin>", line 1     class=4         ^ SyntaxError: invalid syntax >>> self=3

你可能知道,def和class是Python中的關(guān)鍵字,我們不能用它們作為變量名。然而,我們可以在定義函數(shù)的上下文之外使用self作為變量名,這表明它在Python中不是保留關(guān)鍵字。

Python中self的四個(gè)秘密分別是什么

4. 我們必須在這些函數(shù)聲明中使用self嗎?

在上面的例子中,我們重復(fù)引用了greet()函數(shù)。正如我們已經(jīng)討論過的,我們將這個(gè)函數(shù)實(shí)現(xiàn)為一個(gè)實(shí)例方法,這樣它就可以被這個(gè)Student類的所有實(shí)例使用。在這種情況下,self是必需的。下面是一些證據(jù):

>>> class Teacher: ...     def say_hello(name): ...         print('Hello, ' + name) ... >>> teacher = Teacher() >>> teacher.say_hello('John') Traceback (most recent call last):   File "<stdin>", line 1, in <module> TypeError: say_hello() takes 1 positional argument but 2 were given

這里有一些分析。如前所述,當(dāng)實(shí)例teacher調(diào)用say_hello()方法時(shí),發(fā)生的事情是執(zhí)行teacher .say_hello()函數(shù),并將實(shí)例對象teacher和' John '設(shè)置為函數(shù)調(diào)用。這就是為什么錯(cuò)誤說“2是給定的。這與函數(shù)的定義相反,函數(shù)的定義只有一個(gè)參數(shù)(name)。

然而,還有兩件事與這個(gè)謎有關(guān),你可能想知道:

  • 雖然聲明實(shí)例方法需要包含self參數(shù),但它不必命名為self。在這個(gè)場景中使用這個(gè)名稱只是每個(gè)Python程序員都能欣賞的一種約定。下面是一個(gè)例子,它可以被命名為其他東西而不會引起任何問題。盡管它在語法上是正確的,但不推薦使用,因?yàn)樗粫屍渌鸓ython程序員感到困惑:

>>> class Teacher: ...     def say_hello(professor, name): ...         print('Hello, ' + name) ... >>> teacher = Teacher() >>> teacher.say_hello('John') Hello, John
  • 在聲明其他函數(shù)(如類和靜態(tài)方法)時(shí),不需要使用self參數(shù)。對類和靜態(tài)方法的清晰解釋將是以后文章的主題。但我在這里可以展示的是,當(dāng)我們聲明一個(gè)類方法時(shí),函數(shù)確實(shí)有一些類似于在實(shí)例方法中使用self的東西,它通常被稱為cls,引用類對象本身。它與具體實(shí)例無關(guān)。下面是一個(gè)例子:

>>> class Student: ...     def __init__(self, name): ...         self.name = name ...     @classmethod ...     def with_names(cls, first_name, last_name): ...         return cls(first_name + ' ' + last_name) ...  >>> student = Student.with_names('John', 'Smith') >>> student.name 'John Smith'

關(guān)于Python中self的四個(gè)秘密分別是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI