自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解開Python中self的四個(gè)秘密

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

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è)謎。

  1. >>> class Student: 
  2. ...     def greet(self, name): 
  3. ...         print('Good Morning, ' + name) 
  4. ...  
  5. >>> student = Student() 
  6. >>> student.greet('John'
  7. Good Morning, John 

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

[[378103]]

1. 它代表什么?

在開始處理這個(gè)謎題之前,我們需要理解兩個(gè)基本的相關(guān)概念:類和實(shí)例。當(dāng)然,解決所有這些謎題需要額外的知識(shí),而不僅僅是類和實(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)信息。

  1. >>> type(Student) 
  2. <class 'type'
  3. >>> type(student) 
  4. <class '__main__.Student'
  5. >>> isinstance(student, Student) 
  6. True 
  7. >>> hasattr(Student, 'greet'
  8. True 

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

  1. >>> class Student: 
  2. ...     def greet(self, name): 
  3. ...         print(id(self)) 
  4. ...         print('Good Morning, ' + name) 
  5. ...  
  6. >>> student = Student() 
  7. >>> student.greet('John'
  8. 4546580944 
  9. Good Morning, John 
  10. >>> id(student) 
  11. 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í)例方法——一個(gè)對某個(gè)類的實(shí)例可用的函數(shù)。但是,如果我們檢查這個(gè)屬性的類型,就會(huì)顯示一些不同的東西。

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

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

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

  1. >>> Student.greet(student, 'John'
  2. Good Morning, John 

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

  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í)例不會(huì)直接實(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è)簡單的例子:

  1. >>> def=5 
  2.   File "<stdin>", line 1 
  3.     def=5 
  4.        ^ 
  5. SyntaxError: invalid syntax 
  6. >>> class=4 
  7.   File "<stdin>", line 1 
  8.     class=4 
  9.         ^ 
  10. SyntaxError: invalid syntax 
  11. >>> 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ù):

  1. >>> class Teacher: 
  2. ...     def say_hello(name): 
  3. ...         print('Hello, ' + name) 
  4. ... 
  5. >>> teacher = Teacher() 
  6. >>> teacher.say_hello('John'
  7. Traceback (most recent call last): 
  8.   File "<stdin>", line 1, in <module> 
  9. 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è)例子,它可以被命名為其他東西而不會(huì)引起任何問題。盡管它在語法上是正確的,但不推薦使用,因?yàn)樗粫?huì)讓其他Python程序員感到困惑:
  1. >>> class Teacher: 
  2. ...     def say_hello(professor, name): 
  3. ...         print('Hello, ' + name) 
  4. ... 
  5. >>> teacher = Teacher() 
  6. >>> teacher.say_hello('John'
  7. Hello, John 
  • 在聲明其他函數(shù)(如類和靜態(tài)方法)時(shí),不需要使用self參數(shù)。對類和靜態(tài)方法的清晰解釋將是以后文章的主題。但我在這里可以展示的是,當(dāng)我們聲明一個(gè)類方法時(shí),函數(shù)確實(shí)有一些類似于在實(shí)例方法中使用self的東西,它通常被稱為cls,引用類對象本身。它與具體實(shí)例無關(guān)。下面是一個(gè)例子:
  1. >>> class Student: 
  2. ...     def __init__(self, name): 
  3. ...         self.name = name 
  4. ...     @classmethod 
  5. ...     def with_names(cls, first_name, last_name): 
  6. ...         return cls(first_name + ' ' + last_name) 
  7. ...  
  8. >>> student = Student.with_names('John''Smith'
  9. >>> student.name 
  10. 'John Smith' 

英文原文:

Unlock the 4 Mysteries of self in Python | by Yong Cui | Better Programming | Medium

 

 

 

責(zé)任編輯:張燕妮 來源: 今日頭條
相關(guān)推薦

2013-04-11 12:56:14

費(fèi)道明HTML

2022-05-04 12:44:57

Python編程語言

2013-10-22 09:30:22

2022-01-12 15:50:24

JavaScript開發(fā)循環(huán)

2024-11-14 09:00:00

Python編程元編程

2021-08-14 09:48:02

ReentrantLock多線編程

2020-08-13 10:29:55

項(xiàng)目管理項(xiàng)目經(jīng)理CIO

2011-07-14 15:23:34

java

2024-09-26 10:00:00

Python文件處理

2013-03-18 13:31:28

2024-06-25 12:45:05

2024-05-10 12:33:06

flask裝飾器

2022-02-23 15:09:18

數(shù)字化轉(zhuǎn)型國有企業(yè)數(shù)據(jù)

2023-10-26 07:47:35

JavaScript代碼變量

2010-03-30 11:00:46

Oracle 數(shù)據(jù)

2023-08-21 13:39:57

開發(fā)桌面Ubuntu

2010-06-29 09:06:39

Java思想Java虛擬機(jī)

2011-05-18 09:32:14

java

2020-06-04 08:15:53

Kubernetes容器PaaS

2022-06-27 23:31:01

JavaScript框架開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)