热门问题
时间线
聊天
视角
Python
通用高階程式語言 来自维基百科,自由的百科全书
Remove ads
Python(英語發音:/ˈpaɪθən/;英語發音:/ˈpaɪθɑːn/),是一種廣泛使用的直譯式、進階和通用的程式語言。Python支援多種程式設計範式,包括結構化、程序式、反射式、物件導向和函數式程式設計。它擁有動態型別系統和垃圾回收功能,能夠自動管理主記憶體使用,並且其本身擁有一個巨大而廣泛的標準庫。它的語言結構以及物件導向的方法,旨在幫助程式設計師為小型的和大型的專案編寫邏輯清晰的程式碼。
吉多·范羅蘇姆於1980年代後期開始研發Python,作為ABC語言的後繼者[19],它也可以被視為採用了叫做M-表達式的中綴表示法的一種LISP方言[38]。吉多·范羅蘇姆於1991年首次釋出 Python 0.9.0[39]。Python 2.0於2000 年釋出並引入了新功能。Python 3.0於2008年釋出,它是該語言的主要修訂版,並非完全向下相容。Python 2於2020年隨2.7.18版停止支援[40]。
Python的設計哲學,強調程式碼的可讀性和簡潔的語法,尤其是使用空格縮排來劃分程式碼塊。相比於C語言或Java,Python讓開發者能夠用更少的代碼表達想法。
Python直譯器本身幾乎可以在所有的作業系統中執行,它的官方直譯器CPython是用C語言編寫的。Python是一個由社群驅動的自由軟體,目前由Python軟體基金會管理。Python是最受歡迎的程式語言之一[41][42][43][44]。
Remove ads
歷史
Python的創始人吉多·范羅蘇姆,在1982年至1995年間,參與了荷蘭數學和電腦科學研究學會多個專案的工作[45]。1989年的聖誕節期間,他決心開發一個新的指令碼解釋程式,作為ABC語言的後繼者,並且用它替代Unix shell和C語言來進行系統管理[19],擔負與Amoeba作業系統[46]之間的互動操作並進行例外處理[11]。他是BBC電視劇《Monty Python的飛行馬戲團》的愛好者,所以選取了Python作為這個程式語言的名字[47]。范羅蘇姆作為Python的主要開發者,獨自擔負這個專案的發展決策者職責,直到2018年7月12日,他宣布從終身仁慈獨裁者(BDFL)的職位上「永久休假」[48][49]。他參與了2019年第一屆領導專案發展的五人掌控委員會[50][51]。
在1991年2月,范羅蘇姆在Usenet新聞群組alt.sources上釋出了最初程式碼(標記為版本0.9.0)[1],這時就已經存在了帶繼承的類、例外處理、函式和核心類型list
、dict
、str
等。在這個最初發行中就有了從Modula-3引進的模組系統[52],和例外處理機制[11]。在1994年1月,Python版本1.0釋出[53],其主要新特徵是由Amrit Prem提供的函數式程式設計工具lambda
、map
、filter
和reduce
[54]。受Modula-3啟發,Python 1.1介入了參數預設值,Python 1.3介入了關鍵字參數。Python 1.4介入了對複數的內建支援[55]。
在2000年10月,Python 2.0發布,它從函數式程式設計語言Haskell中引進了列表推導式[56]。Python 2.1支援了靜態巢狀作用域[57]。Python 2.2進行了重大革新,將Python中用C語言寫成的類型,和用Python語言寫成的類,統一成在同一個層級中,使得Python的對象模型成為純粹而一致的對象模型[58];還介入了迭代器[59],受CLU和Icon啟發的生成器[60],和描述器協定[61]。Python 2.3介入了從Dylan引進的方法決定次序[17]。Python 2.4介入了集合類型,和函式修飾器[62]。Python 2.5在官方實作中介入了抽象語法樹[63]。
在2008年12月,Python 3.0發布,它對語言做了較大修訂而不能完全後向相容[64],儘管提供了進行自動轉換的2to3
實用工具,仍有大量現存程式碼不能移植,故而Python 2.7的產品壽命結束延期至2020年元旦。Python 3.4介入了非同步I/O模組[65]。Python 3.5介入了類型提示[66],和採用async/await語法的協程[67]。Python 3.8介入了賦值表達式[68][69]。
在2020年10月,Python 3.9介入了內建的針對容器類的泛化別名(types.GenericAlias
)類型[70],並在官方實作中介入了新的語法解析器[71]。Python 3.10介入了從Haskell和OCaml等借鑑來的結構式模式匹配[72],和內建的聯合類型(types.UnionType
)[73]。Python 3.11對官方實作進行了最佳化提速[74]。Python 3.12介入了類型參數語法[75],並廢棄或移除了一些過時的模組和功能。
在2024年10月,Python 3.13介入了從PyPy引進的新互動式直譯器,並實驗性的支援了即時編譯器[76]。Python 3.14正式支援了自由執行緒Python的官方實作建造選項[77]。
每個版本首次發行後,享有2年的完全支援,隨後是3年的安全支援。當前只有Python 3的穩定版本3.12與3.13正在被完全支援,但仍提供對3.9、3.10和3.11版本的安全性修正[78]。
在2024年12月,活躍的Python核心開發者,選舉Pablo Galindo Salgado、Barry Warsaw、Emily Morehouse、Gregory P. Smith和Donghee Na,為2025年度掌控委員會的五位成員來領導這個專案[79]。
Remove ads
特徵與設計哲學
Python是多範式程式語言。它完全支援結構化程式和物件導向程式設計,還有很多特徵支援函數式程式設計和元程式設計比如元對象協定(元類和魔術方法[80])。通過擴充還可以支援很多範式,包括面向方面程式[81]、契約式設計[82]和邏輯程式[83]。
Python使用動態型別,在主記憶體管理上採用的垃圾回收器基於了參照計數[84],並且結合了檢測環參照的分代垃圾回收最佳化[85]。它的特徵還有動態名字解析(後期繫結),即在程式執行期間繫結方法和變數的名字。
Python對遵循LISP傳統的函數式程式設計提供了有限的支援[86],它提供了 map
、filter
和reduce
函式[87];列表推導式、字典推導式、集合推導式和生成器表達式。標準庫中的模組functools
和itertools
,實作了從Haskell和Standard ML借鑑來的函數式工具[88]。
Python的設計理念是「優雅」、「明確」、「簡單」,它的一些重要準則被合稱為「Python之禪」。在Python解釋器內運行import this
可以獲得完整的列表,下面舉出其中首要:
- 優美優於醜陋。明瞭優於隱晦。
- 簡單優於複雜。複雜優於凌亂。
- 扁平優於巢狀。稀疏優於稠密。
- 可讀性很重要。
Python開發者的方法論是「用一種方法,最好是只有一種方法來做一件事」,顯著不同於以Perl語言為代表的「不止一種方法去做一件事」風格。Python開發者在設計語言時,如果面臨多種選擇,一般會選擇明確沒有或者很少有歧義的語法。
范羅蘇姆將Python本身設計為可擴充的[89],並不把所有的特性和功能都整合到語言核心,而是提供了豐富的API和工具,以便程式設計師能夠輕鬆地使用Python、C語言、Cython來編寫擴充模組。Python還可以通過外界函式介面如標準庫中的ctypes等,來提供C語言相容資料類型,並訪問動態連結庫或共享庫中的函式[90],從而對用其他語言編寫的程式進行整合和封裝。
在Python的官方實作CPython中,一般避開不成熟的或者對非重要部位的加快運行速度的優化。在某些對運行速度要求很高的情況,可以使用具備JIT技術的Python實作或安裝JIT擴充模組[91]。
Remove ads
語法和語意
Python為了讓程式碼具備高度的可閱讀性,在設計時盡量使用了其它語言常用的符號和英文單字。
Python程式在詞法分析上被分成若干邏輯行。簡單語句包含在一個單一的邏輯行之內,Python支援使用分號作為分隔符,將多個簡單語句合併入一個邏輯行之中[92]。
注釋開始於並非字串文字一部份的一個井號#
,並結束於物理行結尾;注釋標示邏輯行的結束,除非已受制於隱式行接續規則;注釋在語法上被忽略[93]。
Python支援使用反斜槓作為行接續符,將多個物理行合成為一個邏輯行[94]。在圓括號、方括號或花括號之中的表達式,可以分裂跨越多於一個物理行而不使用反斜槓,這被稱為「隱式行接續」[94]。
Python語法中的複合語句,包含了一些其他語句,它們以某種方式影響或控制這些其他語句的執行。Python的複合語句包含一個或多個子句(clause),子句構成自一個頭部(header)和一個套件(suite)。特定複合語句的子句頭部都在同樣的縮排層級上,每個子句頭部開始於一個唯一標識關鍵字,並結束於一個冒號。套件即語法意義上的塊,是這個子句所控制的一組語句。
套件有兩種形式:可以是與頭部在同一行上的一個或多個由分號分隔的簡單語句,它們跟隨在這個頭部的冒號之後;或者是遵循越位規則的在連續諸行上的一個或多個縮排的語句,只有這種套件形式可以包含巢狀的複合語句[95]。[a]
根據PEP 8的規定[96],使用4個空格來表示每級縮排。[b]
縮排層級的變遷,被用來生成語法解析器才能見到的INDENT
和DEDENT
記號[98],增加縮排就生成INDENT
記號,減少縮排就生成DEDENT
記號。二者的作用相當於C語言家族的花括號,或Pascal語言家族的關鍵字begin
和end
。
Remove ads
Python有如下35個關鍵字;它們不能用作識別碼[99]:
|
|
|
|
|
|
|
內建常數True
、False
和None
於Python版本3.0中成為關鍵字,關鍵字nonlocal
介入於版本3.0[100],關鍵字async
和await
介入於版本3.5[101],並在版本3.7中成為正式關鍵字[102]。
在Python中,將只在特定上下文中保留的識別碼,稱為「軟關鍵字」[103]:
Remove ads
識別碼就是名字,在ASCII範圍內(U+0001..U+007F),可用於識別碼的字元為:大寫字母A
至Z
和小寫字母a
至z
,底線_
以及數字0
至9
,但首字不可以用數字。如下命名約定[104],是為「保留識別碼類」[105]:
_spam
(單底線開頭):弱「內部使用」標識。對於from M import *
,將不匯入所有以底線開頭的對象。spam_
(單底線結尾):為了避免與python關鍵字的命名衝突。__spam
(雙底線開頭):在命名一個類特性的時候,採用名字修飾,比如在類SpamEggs
內,__spam
將變成_SpamEggs__spam
[106]。__spam__
(雙底線開頭雙底線結尾):指那些包含在使用者控制的命名空間中的「魔術」方法或特性,比如__delattr__
、__dir__
、__doc__
、__getattribute__
[107]、__init__
、__new__
、__repr__
、__setattr__
、__sizeof__
等。建議永遠不要將這樣的命名方式應用於自己的變數或函式。
Remove ads
Python的語句包括簡單語句:
- 賦值語句,採用的中綴記號是等號
=
。賦值語句被用來將名字繫結(含重新繫結)到值,以及用來修改可變對象的特性或專案。賦值語句支援鏈式賦值。 - 表達式語句,用來互動式的計算並寫出一個值,或者用來呼叫一個過程(即返回無含義結果的函式),在Python中過程返回值
None
。 global
語句,是在整個當前程式碼塊中成立的聲明,它意味著隨後列出的識別碼被直譯為全域變數。nonlocal
語句,導致隨後列出的識別碼,提及在除了全域作用域之外的最近包圍作用域中的先前繫結變數。del
語句,遞迴的進行刪除。type
語句,聲明作為類型別名類型(typing.TypeAliasType
)的實例的一個類型別名。pass
語句,充當無操作指令,表示此行為空,不執行任何操作。assert
語句,用於程式調適階段時測試執行條件是否滿足。continue
語句,越過這次迭代並繼續進行下個專案。break
語句,從迴圈中跳出。raise
語句,丟擲一個例外。return
語句,用來從函式返回值。當函式執行到return
語句時,它會停止執行並將指定的值返回給呼叫者。yield
語句,用來從一個生成器中返回一個值[110],yield
語句在語意上等價於加圓括號的yield
表達式[111],在函式主體中使用yield
表達式將導致它成為生成器函式。[d]import
語句,匯入一個模組或包,它組合了兩種操作,尋找指名的模組,接著將找到的結果繫結到在局部作用域中的名字。匯入語句有三種形式(下述語句樣本採用了EBNF,這裡的方括號表示其中內容為可選的):
複合語句:
if
語句,當條件成立時執行語句套件。它經常包含elif
、else
子句。while
語句,當條件為真時,重複執行語句套件。for
語句,遍歷列表、字串、字典、集合等迭代器,依次處理迭代器中的每個元素。match
語句,用於模式匹配。class
語句,是定義類的可執行語句。[f]def
語句,是定義函式和方法的可執行語句。[g]async def
語句,用於協程函式定義。await
表達式、async for
語句和async with
語句,只能用在協程函式的主體中。[h]try
語句,它經常包含except
、else
、finally
子句,處理在程式執行中出現的例外情況。Python 3.11介入了except*
子句[117]。Python支援並廣泛使用EAFP(請求原諒比獲得授權更容易)風格的例外處理,作為檢測錯誤狀況和程式中其他「例外」事件的方式。例如:在訪問一個檔案或資源之時,事先不進行測試就嘗試使用它,事後再擷取可能的訪問失敗所引發的例外。[i]with
語句,把一塊程式碼包裹在一個上下文管理器之內。它允許了RAII(對象初始化時取得資源)方式的行為,可替代常見的try
/finally
慣用法。Python使用with
語句處理資源[118],例如:在執行一塊程式碼時,事先取得一個鎖,並且事後釋放這個鎖;或事先打開一個檔案,並且事後關閉這個檔案。[j]
Remove ads
在Python的執行模型中,程式構造自塊(也稱為程式碼塊)。塊是作為一個單元執行的Python程式文字,模組、函式主體和類別定義都是塊。互動式鍵入的每個命令、指令碼檔案和指令碼命令都是塊。傳遞給內建函式eval()
和exec()
執行的字串是塊。塊在執行框架(frame)中執行。框架包含一些用於偵錯的管理資訊,並確定在這個塊執行完成後,執行在何處以及如何繼續。
模組是包含Python定義和語句的一個檔案,這個檔案名字是模組名字附加上字尾.py
;在一個模組中,模組的名字(作為字串)可獲得為全域變數__name__
的值[116]。包(package)是可以包含子模組或遞迴性的子包的模組。包在技術上是具有__path__
特性的Python模組。可以將包視為檔案系統上的目錄,而將模組視為這種目錄中的檔案,但是包和模組不必然源自檔案系統[119]。
名字即識別碼,是通用的參照持有者,它不關聯於一個固定的資料類型,但是,一個名字在給定時間,總是被繫結到有一個類型的某個對象上,這就是動態型別的特徵。名字的儲存位置不「包含」所指示的值,一個共同的值可以賦值給多個名字,一個名字在任何時候,都可以重新繫結到各種不同類型的對象上,包括字串、過程、具有資料和方法的複雜對象等。
如果一個名字繫結在一個塊中,它是這個塊的局部變數,除非被聲明為nonlocal
或global
。如果一個名字繫結在模組層次,它是全域變數。模組對應的塊的變數,既是局部的也是全域的。如果一個變數使用在一個塊中,卻不定義在這裡,它是自由變數[120]。[k]
在Python中,賦值所進行的操作,是將一個名字繫結為到一個分立的動態分配的對象的一個參照。[l] 作用域定義一個名字在一個塊中的可見性。如果一個局部變數被定義在一個塊中,它的作用域包括這個塊。如果這個定義出現在一個函式塊中,作用域擴充到在所界定作用域內包含的任何塊,除非所包含的塊為這個名字介入了不同的繫結。對一個塊可見的所有這種作用域的集合,叫做這個這個塊的「環境」[120]。[m]
當一個名字在一個塊之中使用,它採用最近包圍作用域來解析。如果一個名字繫結在一個塊中,並且在其中於繫結之前就被使用,會導致一個錯誤。[n]當一個函式或類的定義被巢狀到其他函式的定義之內,它的非局部作用域就是這個包圍函式的局部作用域。nonlocal
語句導致其列出的識別碼,提及在非局部作用域內先前繫結的名字(即非局部變數)[120]。[o]
名字空間是儲存變數的地方,它被實作為字典。有局部名字空間、全域空間即包含這個塊對應的模組的名字空間,和內建名字空間即模組builtins
的名字空間;對象的方法是定義在類主體內的函式,它有著巢狀的名字空間。名字空間通過防止命名衝突而支援了模組性,還通過明晰了哪個模組實作了哪個函式而增進可讀性和可維護性。
如果global
語句出現在一個塊之中,在這個語句中指定的所有名字,提及在頂層名字空間中這些名字的繫結。名字在頂層名字空間解析,首先尋找全域名字空間,未果尋找內建名字空間。global
語句與在同一個塊中的名字繫結運算有同樣的作用域。如果一個自由變數的最近包圍作用域包含針對它的global
語句,這個自由變數被當作全域的[120]。[p]
Python的表達式主要包括如下:
- 在Python中,加圓括號(parenthesized)形式被歸類為原子,它是包圍在圓括號中的可選的表達式列表。加圓括號的表達式列表產生的東西,就是這個表達式列表所產生的:如果這個列表包含至少一個逗號,例如
(a,b,c)
,則它產生一個元組;否則它產生的就是這個單一表達式,例如(a)
產生a
[123]。要表示僅有單個元素的元組,需要給這個元素字尾一個逗號,例如(a,)
。空的圓括號產生空元組對象。元組不是圓括號形成的,而是使用逗號形成的,在沒有歧義的情況下,元組的圓括號是可選的。
- Python提供了稱為展示(display)的特殊語法來構造列表、字典或集合,展示被歸類為原子,並且有兩種方式:要麼其所包容的元素是顯式的列舉出來的,要麼它們是通過叫做「推導式」的特定迴圈和過濾指令運算出來的。列表展示,是包圍在方括號中的可以為空的一系列表達式,例如
[a,b,c]
。字典展示,是包圍在花括號中的可能為空的一系列的用冒號:
分隔的鍵-值對。集合展示,是包圍在花括號中的一系列表達式[124]。[q]
- Python支援列表推導式和更一般性的生成器表達式[125],Python 3.0增補了字典推導式和集合推導式。[r]自從Python 3.5,介入了在表達式列表中的「可迭代解包」
*
,和在字典展示中的「字典解包」**
[126]。[s]
- Python對容器類實例,比如序列類型的列表、元組或字串,支援形如
a[索引]
的下標,和形如a[开始:停止]
或a[开始:停止:步长]
的分片。此二者與函式呼叫和特性參照,一起被歸類為表示語言中最緊密運算繫結的初等項(primary)。這裡的下標索引是基於零的,負數是相對於結尾的。分片範圍自從開始索引,直到但不包括停止索引,分片的第三個步長參數,允許元素被跳過和用負數指示反向。分片的每個元素都是淺層複製的。分片索引可以省略,例如a[:]
,這返回整個列表的一個複本。[t]
- 在Python中,算術運算的加法
+
、減法-
、乘法*
,與C語言和java相同的。除法和模除%
的行為有所不同,在Python中有兩種除法:除法/
和下取整除法//
。Python增加了指數算符**
。自從Python 3.5,介入了矩陣乘法算符@
[127],它已經用於了NumPy庫[128]。中綴算符+
、-
,還可以分別表示取原數和取相反數的一元算符。
- 在Python中,有如下必須用於整數的位運算:AND(與)
&
、OR(或)|
、NOT(非)~
、XOR(互斥或)^
、右移>>
、左移<<
。
- 在Python中,有如下比較運算:大於
>
、小於<
、大於等於>=
、小於等於<=
、等於==
、不等於!=
,用來比較兩個對象的值的大小。Python有同一性測試算符:is
、is not
,用來比較兩個運算元是否參照了同一個對象;還有成員關係測試算符:in
、not in
,用於判斷一個對象是否屬於另外一個對象。Python允許由比較運算連結起來的布林表達式[129],比如a < b < c
,它測試a < b and b < c
;C語言將它解析為(a < b) < c
:即首先求值a < b
得出結果0
或1
,接著將此結果比較於c
[130]。
- Python的條件表達式表示為
x if c else y
。意思是當c
為真時,表達式的值為x
,否則表達式的值為y
。 在運算元的次序上不同於很多其他語言中常見的c ? x : y
。
Python中運算子具有優先級,下表中的運算子按照從最高(最先繫結)到最低(最後繫結)的次序列出。在相同儲存格中運算子具有相同的優先級,它們從左至右結合,除了指數表達式和條件表達式從右至左結合之外[133]:
Python為序列提供了串接算符+
和倍增算符*
[134]。自從Python 3.9,介入了字典合併算符|
和字典更新算符|=
[135]。
Python為集合提供了集合論運算:併集|
、交集&
、相對補集-
、對稱差^
,和子集測試<=
、真子集測試<
、超集測試>=
、真超集測試>
。
在Python中,語句不能成為表達式的一部份,表達式比如列表推導式和字典推導式以及lambda
表達式,都不能包含語句。這個限制的一個範例:賦值語句比如a = 1
,不能用作條件語句的條件判斷表達式的一部份;這能夠避免C語言程式中的一個常見錯誤,即在條件判斷時把等於算符==
誤寫為賦值算符=
,這不是預期程式碼卻在語法上有效而能通過C語言編譯器檢查,在Python中這會導致一個語法錯誤。
Remove ads
Python的二元算術運算,先將兩運算元轉為共同類型,加法、減法、乘法、下取整除法、模除和指數運算的結果也採用此類型,舉下取整除法//
例子:5//2 == 2
而5.0//2 == 2.0
。自從Python 3.0,除法/
總是產生浮點數結果,例如5/2 == 2.5
。
下取整除法//
的修約是朝向負無窮的,這意味著等式(a + n)//n == a//n + 1
永遠成立;很多其它程式語言比如C99採用截尾取整規則,其整數除法不能保證這個等式永遠成立。Python提供了round()
內建函式,用於把一個浮點數修約成最近的整數[136],自從Python 3.0,為了打破平局它採用了IEEE 754的約半成偶規則,例如round(1.5) == 2 == round(2.5)
。
模除%
同樣採用下取整規則,它所得餘數的符號同於除數,例如-5%2 == 1
而5%-2 == -1
。很多其它語言採用截尾取整規則,其模除所得餘數的符號同於被除數。Python模除運算結果餘數的定義,確使等式a == (a//n)*n + a%n
對於a
和n
分別為正數或負數的情況均為成立[137];數學中的歐幾里得除法,同樣保證這個等式永遠成立,但它的餘數總是非負數。
Python對所有整數運算,使用任意精度算術。在decimal
模組中的Decimal
類[138],提供十進制浮點數,具有使用者可按需要而更改的預設28個十進制有效數位精度,並有多種修約方式[139]。在fractions
模組中的Fraction
類,提供任意精度的有理數[140]。第三方庫gmpy2[141],提供了到任意精度計算庫GMP/MPIR、MPFR和MPC的介面。
除了求絕對值函式abs()
列入內建函式之外,大多數數學函式,處於math
和cmath
模組內。前者用於實數運算,而後者用於複數運算。Python有著廣泛的數學庫,特別是第三方庫NumPy進一步擴充了原生能力。
Remove ads
Python的文字序列類型,包括字串str
和位元組序列bytes
與bytearray
。文字序列的文字有多種寫法:
- 短字串文字,由單引號
'
或雙引號"
界定。不同於Unix shell、Perl和受Perl影響的語言,單引號和雙引號功能相同。這二種字串都使用反斜槓\
作為跳脫字元。
- Python允許多個毗鄰的字串文字或位元組文字(它們以空白分界並可以使用不同的引述約定),在編譯時間於語法層面上串接起來。要在執行時間串接字串,必須使用序列串接算符
+
[142]。
自從Python 3.0,字串類str
提供了格式化方法format()
[143],例如"spam={0} eggs={1:04d}".format("blah", 2)
,它求值為'spam=blah eggs=0002'
。格式化方法被推薦用來替代早先的字串對象內建格式化算符%
,它在功能上類同於C語言中的printf
格式化字串[144],例如"spam=%s eggs=%04d" % ("blah", 2)
。
自從Python 3.6,介入了字串插值[145],即「格式化字串文字」或稱為「f字串」,它向字串文字字首上f
或F
[146],例如x="blah"; y=2; f'spam={x} eggs={y:04d}'
。

Python使用鴨子型別,並擁有有類型的對象,和無類型的變數名字。在編譯期不檢查類型約束,而寧願在一個對象上的操作出現可能的失敗,表現出這個給定對象不具有適合的類型。儘管是動態型別系統,Python卻是強型別的,禁止沒有明確定義的操作,比如將一個數和一個字串相加,而不是默默的去嘗試轉換使其有意義。
Python有著範圍廣泛的基本資料類型。同時具備常規的整數和浮點算術,它透明的支援任意精度算術、複數和十進制浮點數。Python支援種類繁多的字串操作。在Python中,字串是不可變的,所以在其他程式語言中可能就地改變字串的字串操作,比如字元替換,在Python中返回新的字串。
Python有一個非常有用特徵,就是搜集(或稱容器)類型的概念。一般的說,搜集是以一種易於參照或索引的方式,包含其他對象的對象。Python的搜集類型包括了序列、對映和集合,Python提供了廣泛的搜集操縱能力,比如內建包含檢查和通用迭代器協定。
列表(動態陣列)、元組和字串是序列類型。所有序列類型都有位置索引,並且除了字串,都可以包含任意類型的對象,在同一個序列中可以包括多種類型的對象。字串和元組是不可變的,使得它們成為字典的鍵的完美候選者。列表是可變的,元素可以被插入、刪除、修改、添加或就地排序。
字典是無次序的對映類型,它將一組不可變的鍵,對映到相應的元素上。在字典中的鍵,必須是不可變的Python類型,比如整數或字串,因為在底層它們是通過雜湊函式實作的。集合是無次序的類型,它包含唯一性的不可變對象作為元素。有二種類型的集合:可變的set
和不可變的frozenset
。
Python允許程式者使用類,定義自己的類型[58]。類的新實例,是通過呼叫這個類的構造器而建立的,而類型和類都是元類type
的實例,元類type
更是其自身的實例,這允許了元程式設計和反射。Python支援對類型和類的廣泛內省,它們可以被讀取和比較。[w]
長期規劃是支援漸進類型[7],並且自從Python 3.5,語言的語法允許指定靜態型別,但在預設實作CPython中不檢查它們[148]。靜態型別檢查器mypy,支援編譯期型別檢查[149]。
除了各種資料類型,Python直譯器還內建了很多其他類型,包括可呼叫類型:使用者定義函式、實例方法、生成器函式、協程函式、非同步生成器函式、內建函式、內建方法、類、類別方法;模組,客製化類,類別實例,I/O對象(也叫做檔案對象),和暴露給使用者的一些內部類型:程式碼對象、框架對象、溯回對象、切片對象、靜態方法對象、類別方法對象。
Python的函式支援閉包[156],及其他頭等函式特徵[x],並支援限制最大深度的遞迴[y], 它不支援函式多載。Python的函式作為頭等對象,具有和普通對象平等的地位。Python官方實作不提供尾呼叫最佳化或頭等續體,吉多·范羅蘇姆曾聲稱他不會對其加以支援[157],有第三方庫支援彈跳床[158]。
在Python中,函式呼叫的實際參數與函式定義的形式參數之間的結合,所傳遞的是「對象參照」,函式在被呼叫之時,所給予的實際參數被介入到一個局部符號表中,實際參數使用傳值呼叫來傳遞,而這個值總是對象參照,並非這個對象的值[159]。如果形式參數繫結到一個可變對象,則通過形式參數對此對象內容的修改,在函式外也是可見的。如果形式參數繫結到一個不可變對象,則通過形式參數不能修改此對象內容,但可以把形式參數重新繫結到其它對象上,這並不影響函式外的對象的值。[z]
Python在函式定義時,可以在形式參數序列中,以形式参数=值
的樣式指定形式參數預設值。在函式呼叫時可以省略有預設值的形式參數,這時這個預設值就被代入到它的位置中。在這個函式定義被執行之時,從左至右的求值作為形式參數的預設值的這些表達式。這意味著這種表達式在這個函式被定義之後只被求值一次,而每次函式呼叫之時都使用相同的「預先計算」的值。[aa]
Python在函式呼叫中,可以給予位置實際參數和關鍵字實際參數。實際參數可以如同C語言那樣,按照位置與函式定義的形式參數匹配;也可以採用關鍵字實際參數,即形式参数=值
樣式的實際參數。Python在函式定義中,可以使用不對應實際參數的特殊形式參數/
和*
,將形式參數序列分為三部份:唯位置形式參數、可位置可關鍵字形式參數和唯關鍵字形式參數。如果一個形式參數有預設值,則在其後直到*
之前的所有形式參數也都必須有預設值。[ab]
在函式定義中的位置形式參數序列和關鍵字形式參數序列,可以分別在其末尾有*args
或**kwargs
這樣的加了字首*
或**
的形式參數,它們擷取在函式呼叫時提供的,超出形式參數序列規定而無所對應的多個實際參數;在形式參數args
前加*
號,則args
是元組類型,它擷取可變數目的位置實際參數;在形式參數kwargs
前加**
號,則kwargs
是字典類型,它擷取可變數目的關鍵字實際參數。[ac]
在函式呼叫的實際參數序列中,關鍵字實際參數必須出現在位置實際參數之後。如果要傳遞給一個函式的一些位置實際參數,已經在一個序列類型如列表或元組的對象中,則可以在函式呼叫中給它字首*
來進行可迭代解包;如果要傳遞的一些關鍵字實際參數已經在字典對象中,則可以給它加**
號來進行字典解包。
在函式定義頭部之後可以插入「文件字串」,用作函式的使用幫助,它可以使用內建函式help()
列印出來。自從Python 3.0,函式定義可以對形式參數與返回值增加類型標註[160]。自從Python 3.5,開始支援類型提示[148]。
Python的修飾器(decorator)可用來修改任何可呼叫Python對象,其用法是將已定義的對象比如函式、方法或類別定義傳遞給修飾器,再將它所返回的修改後的對象繫結到原來對象的名字。修飾器可用於元程式設計,其用途至少包括:建立類別方法或靜態方法,設定先決條件和後置條件、實作多方法、記憶化[161]。
Python使用@
作為關鍵字形成修飾詞,它是用來應用修飾器的語法糖。[ad]
通過在毗連的行上放置多個修飾詞,多個修飾器可以連結起來應用。[ae]
Python支援大多數物件導向程式設計技術。在Python中所有東西都是對象,包括數、函式、類和模組。它允許多型性,不限定於在類層級之內子類型方式,而是採用了鴨子型別方式[5],就是說針對變數的方法呼叫和特性(attribute)訪問,不事先限制這個的變數的類型,它可被繫結到任何對象。Python的類繼承支援多重繼承,這可以用來實作混入。Python支援元類[162],還支援抽象基礎類別[163],自從Python 3.6,提供了客製化化類建立的簡單機制[164]。
對象的方法,是附屬於這個對象的類的函式。對於正常的方法和函式,語法实例.方法(实际参数)
,是类.方法(实例, 实际参数)
的語法糖。Python不提供其他一些物件導向程式設計語言比如C++和Java中的隱式的this
關鍵字[165],Python的對象方法沿襲自Modula-3,使用顯式的第一個形式參數來訪問實例特性,習慣上將其命名為self
。[af]
Python支援一些名字以__
開始和結束的特殊方法,它們用於實作實作多種特殊功能[80],尤其是實例初始化,在一個類中定義__init__()
,它在實例建立後返回給呼叫者之前被呼叫,所給予的實際參數就是傳遞給對象構造器表達式的那些實際參數。某些特殊方法可以實作運算子多載,比如在一個類中定義__add__()
,將允許在這個類別的實例上使用+
算符。
在Python中,對象的特殊特性__dict__
,是儲存其所有(可寫)特性的字典[166]。在一個類中的類別變數__slots__
,可以被賦值為變數名字序列,它為所聲明的這些變數在類別實例對象中保留空間,並阻止其自動建立__dict__
[167]。[ag]
在Python中,定義了一個或多個特殊方法__get__()
、__set__()
、__delete__()
的類,可以用作描述器(descriptor)[168]。在類的定義中,如果一個成員若是另一個描述器類別的實例,則它被稱為這個類的屬性(property),使用與特性(attribute)訪問相同的語法,訪問這個類別的實例對象中的屬性。[ah]
在Python中,不強制採用訪問子與變異子方法,來訪問對象的資料成員。Python使用名字修飾,有限的支援私有變數[106]。Python的property
內建函式和@property
修飾詞,將一個類中特殊定義的訪問某個特性的那些方法,包裝成的這個類的一個屬性[169]。[ai]
Python允許通過使用@classmethod
和@staticmethod
修飾詞,來分別建立類別方法和靜態方法[62]。在方法呼叫之時,類別方法接收這個類的作為其隱式的第一個實際參數,而靜態方法不接收隱式的第一個實際參數。[aj]
Python不提供隱式的super
關鍵字而是提供了super()
內建函式,在一個類的方法中呼叫此函式返回一個代理(proxy)對象,它為了在類層級內這個類所有基礎類別中尋找實作了特定方法的基礎類別,確定了優先次序即方法決定次序(MRO),次序居前的基礎類別優先於位居其後的它的父輩類或平輩類[170]。當一個子類的方法覆蓋了其超類方法的時候,可通過呼叫super().方法
,將這個方法呼叫委託給與子類的self.方法
同名的超類別方法。[ak]
標準庫
Python擁有一個強大的標準庫[171]。Python標準庫包括了如下功能:
程式碼實例
一個在標準輸出裝置上輸出Hello World的簡單程式,這種程式通常作為開始學習程式語言時的第一個程式,可將如下程式碼錄入純文字檔案並隨意命名比如program01.py
,然後執行這個程式python3 program01.py
:
print("Hello, world!")
Python也可以單步直譯執行。執行Python直譯器進入互動式命令列的環境,你可以在提示符號>>>
旁輸入print("Hello, world!")
,按Enter鍵輸出結果:
>>> print('Hello, world!')
Hello, world!
計算正數的階乘的程式碼:
n = int(input('輸入一個數,就會印出其階乘: '))
if n < 0:
raise ValueError('錯誤,請輸入一個非負整數')
fact = 1
for i in range(2, n + 1):
fact *= i
print(fact)
注意,在Python 3.0及以上版本中,print
是個函式,需要在要列印的字串前後加上圓括號;在Python 2.6以下版本中,print
是一個關鍵字和命令而不加圓括號。
實作
Python是一門跨平台的手稿語言,Python規定了一個Python語法規則,根據該規則可編寫Python直譯器[172]。Python屬於動態語言,其官方實作CPython將Python程式編譯成中間形式的位元組碼[173],並接著在它的虛擬機器上執行[174],執行速度緩慢於C/C++所編譯出的機器碼和在HotSpot JVM上執行的java位元組碼[175]。
- 活躍開發的實作
- CPython:官方的Python直譯器,需要區別於其他直譯器的時候才以CPython稱呼。CPython預設採用全域直譯器鎖(GIL),以確保在任何時刻只有一個執行緒執行Python位元組碼;一些擴充模組被設計為在進行計算密集任務時釋放GIL,還有在進行I/O時總是釋放GIL[176]。
- MicroPython:為微控制器而最佳化的Python 3變體,它實作了完整的Python 3.4語法,和補充自版本3.5的
async/await
關鍵字,以及後來版本的一些選定特徵;它提供了實作Python標準庫模組功能子集的內建模組,和特定於微控制器的一些模組。CircuitPython是Adafruit開發的MicroPython分叉。 - PyPy:採用了跟蹤JIT的Python實作,預設支援stackless模態[177],它是用RPython編寫的,當前支援Python版本3.11和2.7。
- Numba:使用LLVM JIT的Python最佳化編譯器,它將包括很多NumPy函式的聚焦數值計算的Python子集,翻譯成快速的機器碼,它為在CPU和GPU上並列化Python程式碼提供了大量選項。
- Codon:高效能且無執行時開銷的Python編譯器[178],它將Python程式碼編譯成本機機器碼,並且支援本機多執行緒和GPU並列運算,還包括了特徵齊全的完全編譯的內建NumPy實作。它由MIT CSAIL的研究人員開發[179],其語意在資料類型等方面上與CPython有所不同[180]。
- Pyodide:基於WebAssembly/Emscripten的用於瀏覽器和Node.js的Python釋出[181],支援任何在PyPI上
wheel
形式的純Python包,並且已經移植了很多具有C語言擴充的包。 - RustPython:用Rust編寫的Python直譯器[182],它可以嵌入到Rust應用程式中從而將Python用作手稿語言,還可以被編譯成WebAssembly從而在瀏覽器中執行Python程式碼。
- Brython:用JavaScript編寫的在瀏覽器中執行的Python實作[183],具有到DOM元素和事件的介面。
- GraalPy:針對JVM的基於GraalVM的Python高效能實作[184]。
- 轉譯成其他語言的編譯器
- Cython:將增加了靜態型別聲明的Python超集編譯成C或C++的編譯器。Cython補充支援呼叫C語言函式並且在變數和類特性上聲明C語言類型,還支援以OpenMP為後端的本機多執行緒並列[185]。
- mypyc:將Python模組編譯成C擴充的編譯器[186],它使用標準的Python類型提示生成快速程式碼。mypyc是mypy發行的可選依賴,它使用mypy進行型別檢查和類型推論[149]。
- Nuitka:用Python編寫的到C11(或替補為C++03)的編譯器[187],它依賴於CPython的
libpython
庫,能完成嵌入所有模組的程式編譯、擴充模組及包編譯和獨立模態程式釋出。 - Shed Skin:將純粹但隱含為靜態型別的Python有限子集程式碼轉譯成最佳化的C++程式碼的編譯器[188],它可以生成獨立程式或者能匯入並用於更大Python程式的擴充模組。
- Pythran:將聚焦於科學計算的Python子集編譯成C++11的提前編譯器[189],它依賴於Boost和xsimd庫,將標註了介面描述的Python模組編譯為本機共享庫模組,能利用上多核和SIMD指令單元。
- Transcrypt:用Python編寫的Python 3.9到JavaScript編譯器[190],用於在瀏覽器中執行Python程式碼,它被預先編譯為高可讀性且高效的JavaScript程式碼。
- MyHDL:將Python編譯成Verilog或VHDL[191]。
其他實作舉例:Jython,它是用Java實作的Python 2.7。IronPython,它是建造在DLR之上的Python 2.7和Python 3.4實作。Stackless Python,它是實作微執行緒的CPython 3.8分叉。Pyston,它是具有JIT等效能最佳化的CPython 3.8.12的分叉[192]。Pyjion,將Python程式碼編譯成本機CIL的CPython 3.10的JIT擴充[193]。Cinder,它是Meta孵化器釋出的具有包括JIT等很多最佳化的CPython 3.10分叉[194]。Grumpy,它是Python 2.7到Go的轉譯器和執行時系統[195]。py2many,起步於轉譯至Julia的PyJL的將Python轉譯成多種語言的轉譯器[196]。
開發環境
很多並非整合式開發環境軟體的文字編輯器,也對Python有不同程度的支援,並且加上專門為Python設計的編輯器外掛程式也會有很高的可用性。
適用於Python的整合式開發環境(IDE)軟體,除了標準二進制釋出包所附的IDLE之外,還有許多其他選擇。其中有些軟體設計有語法著色、語法檢查、執行偵錯、自動補全、智慧型感知等便利功能。由於Python的跨平台出身,這些軟體往往也具備各種作業系統的版本或一定的移植性。
- IDLE:Python「標準」IDE,一般隨Python而安裝,支援較少的編輯功能,偵錯功能也比較弱。
- Eric:基於PyQt的自由的IDE,支援自動補全、智慧型感知、自動語法檢查、工程管理、svn/mercurial整合、自動單元測試等功能,具有可延伸的外掛程式系統,通過可選外掛程式支援Git整合。偵錯功能與Visual Studio和Eclipse類似。
- Spyder:開源的跨平台科學計算IDE。
- PyCharm:由JetBrains公司出品,具備一般IDE的功能,比如偵錯、語法突顯、Project管理、程式碼跳轉、智慧型提示、自動完成、單元測試、版本控制等等,另外,它還提供了一些功能用於Django開發,還支援IronPython。它是商業軟體,但也具有社群版和教育版。
第三方擴充包

Python社群提供了大量的功能覆蓋眾多領域的第三方模組,其使用方式與標準庫類似。第三方模組可以使用Python/Cython或者C語言編寫。軟體工具比如SWIG,通過定義介面檔案或規定檔案的方式,可以將C/C++編寫的程式庫包裝為Python模組。Python直譯器本身也可以被整合到其它需要手稿語言的程式內。
Python包索引是公開的軟體套件線上倉庫。pip是官網推薦的以安全方式安裝Python應用及其依賴軟體套件的最流行工具[197]。要安裝在整個作業系統範圍內共享的Python包,現在需要通過作業系統的軟體套件管理系統。要將特定於應用的依賴包隔離於共享的Python安裝,可以使用標準庫的venv[198]或第三方工具virtualenv[199]建立虛擬環境;第三方工具pipenv,能自動為使用者專案建立和管理虛擬環境,並在安裝/卸裝軟體套件的時候,向此專案的Pipfile檔案增加/移除這個軟體套件[200]。
Python標準庫對於各種網路協定的支援很完善,因此適用於編寫伺服器軟體、網路爬蟲等Web開發。Python定義了WSGI標準應用介面,來協調HTTP伺服器與基於Python的Web程式之間的溝通。比如,通過mod_wsgi模組,Apache HTTP Server可以運行用Python編寫的Web程式。
用Python編寫的一些Web框架,有助於輕鬆地開發和管理複雜的Web程式。重要的第三方網路程式庫和Web框架有:
- Zope:著名的開源Web應用伺服器。
- Beautiful Soup:用作HTML/XML解析器的一個簡單易用Python包。
- Twisted:事件驅動的網路程式框架,它支援很多常見的網路協定並包括了很多不同用途的模組,它支援所有主要的系統事件迴圈和各種GUI事件迴圈。
- Django:MTV架構[201]的Web框架,它注重組件的重用性和「可插拔性」、快速開發和DRY法則。
- Tornado:使用單執行緒事件迴圈的非同步非阻塞式web伺服器,也是輕量級的Web框架。
- Flask:微Web框架,不要求特定的工具或庫。
- Requests:適合於常人使用的HTTP庫,封裝了許多繁瑣的HTTP功能,極大地簡化了HTTP請求所需要的程式碼量。
- aiohttp:基於
asyncio
的HTTP客戶端和伺服器二者[202]。 - uvloop:對內建
asyncio
事件迴圈的快速的、直截了當的替代者[203],它用Cython實作並在底層使用了libuv。 - FastAPI:用來建造基於HTTP的網路服務API的現代高效能web框架[204]。
- PyScript:建立在瀏覽器內的Python應用的框架[205],可採用Pyodide、MicroPython、WebAssembly和當代Web技術。
Python本身包含了Tkinter庫,它是Python的業界標準GUI並被整合進入了IDLE。Tkinter基於了Tcl命令工具,能夠支援簡單的GUI開發。但是為了讓所開發的軟體執行速度更快,並與使用者的桌面環境更契合,人們一般會選擇採用第三方GUI庫或框架。主要的第三方GUI庫有:
- PyQt:Qt的Python繫結庫,由Riverbank Computing公司自從1998年發行,採用GPL授權條款或商業授權條款。
- PySide:Qt的Python繫結庫,由Qt公司自從2009年發行,採用LGPL授權條款。
- PyGObject:替代了PyGTK,它是為Python程式訪問基於GObject的庫而提供的包裝庫[206],GObject是GTK、GIO和GStreamer等庫使用的對象系統。
- Kivy:用於開發多點觸控應用軟體的開源Python庫,採用了自然使用者介面(NUI)。
- WxPython:GUI程式框架wxWidgets的Python包裝庫。
- Gooey:將幾乎所有Python 3控制台程式用一行程式碼轉變成GUI應用[207]。
- Dear PyGui:快速而強力的具有極小依賴性的GUI工具箱[208]。
- pywebview:輕量級跨平台的對WebView構件的包裝器,允許在其本地GUI窗口中顯示HTML內容[209]。
重要的資料科學用第三方軟體庫有:
- NumPy:Python的基礎性的科學計算軟體庫,它提供了強力的多維陣列對象,廣播式陣列運算[210],整合C/C++和Fortran程式碼的工具,較為有用的線性代數、傅立葉變換和亂數功能。
- SciPy:用於數學、科學和工程的Python軟體庫,它以NumPy的多維陣列作為基本資料結構,所包含的模組針對了:統計、最佳化、數值積分、常微分方程求解、插值、線性代數、傅立葉變換、訊號處理、圖像處理等。
- CuPy:NumPy/SciPy相容的GPU加速的陣列庫[211],它可在NVIDIA CUDA或AMD ROCm平台上充當其直截了當的替代者,來執行現存的NumPy/SciPy程式碼。
- matplotlib:基於NumPy的綜合性繪圖庫,用於建立靜態的、動畫的和互動式的資料視覺化。
- pandas:用於資料分析和資料操縱的軟體庫,它建造在NumPy基礎上,提供了加標籤資料結構「資料訊框」[212],和統計函式等。它的預設繪圖後端是matplotlib,還可以擴充上第三方繪圖後端[213]。
- Dask:伸縮範圍從筆記型電腦至電腦叢集的平行計算庫[214],它提供的使用者介面鏡像了PyData生態系統中pandas、scikit-learn和NumPy的API。
- VisPy:高效能互動式2D/3D資料視覺化庫[216],它通過多種後端OpenGL庫之一來顯示非常大的資料集,並提供叫做gloo的受用NumPy的Python風格OpenGL ES 2.0介面。
- glumpy:用於科學資料視覺化的快速、可伸縮的Python庫[217],它基於了NumPy和OpenGL繫結庫PyOpenGL。
- seaborn:基於matplotlib的資料視覺化庫[218],它提供了繪製統計圖形的高層介面。
- Vega-Altair:建造在Vega-Lite JSON規定之上的聲明式統計視覺化庫[219]。
- Bokeh:針對現代Web瀏覽器的互動式資料視覺化庫[220],它在大型或串流的資料集上提供高效的互動性。
- plotly:互動式開源的基於瀏覽器的圖形繪製庫[221],它是建造在plotly.js之上的聲明式圖表庫。
- Dash:資料應用和儀錶板框架,它可將現代使用者介面元素如下拉選單、滑動條和圖形,直接連結至分析型Python程式碼[222],它由Plotly公司出品,基於了React、Flask和plotly.js[223]。
- Panel:資料探索和Web應用框架,它能無縫的整合於PyData生態系統,提供互動式資料表格和視覺化等功能[224],它可用在Pyodide和PyScript之中[225]。Panel是HoloViz生態系統的成員[226],這個工具組還包括了:hvPlot、HoloViews、GeoViews、Datashader、Lumen、Param和Colorcet。
- Streamlit:迅速將Python指令碼轉變為Web應用的框架[227],所生成的應用可共享於Streamlit社群雲平台。
- Voilà:將Jupyter Notebook轉變為獨立的Web應用的框架[228]。
基礎性的機器學習軟體庫及框架有:
- scikit-learn:機器學習軟體庫,它提供的功能包括:監督學習中的分類和回歸,無監督學習中的聚類和降維,還有模型選擇和資料預處理。它基於了NumPy、SciPy、輕量級管道庫Joblib[229]和執行緒池控制庫threadpoolctl[230],其繪圖功能依賴於matplotlib,還用到了scikit-image、seaborn和plotly。
- PyMC:基於從Theano分叉出的PyTensor的概率程式庫,它用於建立貝葉斯統計模型,並使用馬爾可夫鏈蒙特卡洛(MCMC)方法進行模型擬合。
- TensorFlow:Google開發的「端到端」開源機器學習平台,它提供了Python API[231],其中實作了Keras API[232]。Keras現在是在TensorFlow 2上建立的深度學習高層API。
- PyTorch:Meta在Torch基礎上開發的開源的Python軟體套件,提供了具有強大的GPU加速的張量計算,和建立在基於tape的自動微分系統上的深度神經網路。
- JAX:Google開發的開源機器學習框架,其核心是可任意組合的對數值純函式的變換[233],它結合了修改版本的針對NumPy的自動微分庫Autograd[234],和TensorFlow中的加速線性代數庫XLA[235],它使用XLA來在GPU和TPU上編譯和執行NumPy程式。
- pegen:Python的PEG解析器生成器[236]。
- PeachPy:採用高層Python的可移植高效x86-64組譯程式碼生成器[237]。
- llvmlite:輕量級的LLVM的Python繫結,用於編寫即時編譯器[238]。
- xDSL:圍繞靜態單賦值(SSA)中間表示(IR)建造的Python原生的編輯器框架[239],它的設計受到了MLIR編譯器框架的影響。
- SymPy:支援數學符號運算的軟體庫,用於提供電腦代數系統。
- SimPy:基於由Python生成器函式定義的行程的離散事件類比框架[240]。
- ModernGL:不同於PyOpenGL[241],ModernGL是在OpenGL 3.3+核心上的Python包裝器[242],它簡化了簡單圖形應用如科學類比、遊戲和使用者介面的建立。
- PyCUDA:不同於Nvidia的cuda-python[243],PyCUDA提供對CUDA API的Python風格訪問[244]。
- PyOpenCL:PyOpenCL提供對OpenCL API的Python風格訪問[245],例如光滑粒子流體動力學框架PySPH的效能關鍵部份用Cython和PyOpenCL實作[246]。
- Kompute:基於Vulkan的通用計算框架[247],它是高速的、支援行動裝置、非同步的並且針對進階GPU資料處理用例做了最佳化。
- SQLAlchemy:Python的SQL工具包和採用資料對映器模式的對象關係對映器(ORM)。
- Graphene:GraphQL框架[248],支援各種資料來源如SQLAlchemy、Mongo、Django和客製化Python對象等。GQL是常用來與之配合的GraphQL客戶端Python庫[249]。
- Pillow:基於Python的圖像處理軟體庫[250],它支援廣泛的圖形檔案格式,分叉於已終止的PIL。
- Fabric:經由SSH遠端執行shell命令的高層庫[251],它產生有用的Python對象作為回饋。
- Prefect:現代工作流程編排框架[252],它易於建造、排程和監控健壯的資料管線。
- pygame:開發電動遊戲的Python軟體庫,基於了SDL軟體庫[253]。視覺小說引擎Ren'Py建造在pygame之上。
- pyglet:Python編寫的物件導向的遊戲和多媒體庫,利用了FFmpeg軟體庫並需要OpenGL 3.3+。2D街機遊戲開發庫Arcade基於了pyglet[254],它還利用了建造在2D物理引擎Chipmunk之上的Pymunk[255]。
- Panda3D:開源遊戲引擎,包括了圖形、音訊、I/O、碰撞偵測和其他與3D遊戲有關的功能,使用Python作為遊戲開發語言[256]。
- pythonnet:可以近乎無縫的整合.NET通用語言執行庫(CLR)的程式包[257]。
- PyInstaller:將Python應用和它的依賴項捆綁成一個單一的包[258],從而不需要安裝Python直譯器或任何模組就可以執行應用。
應用
在很多作業系統裡,Python是標準的系統元件,它被列入了ISO/IEC 23360-1-4:2021 Linux標準規範(LSB)之語言規定[259]。大多數Linux發行版和macOS都整合了Python,可以在終端模擬器或虛擬控制台下直接執行Python。第三方工具pipx,可以將Python應用安裝於隔離的環境中並在其中執行它[260]。
雖然Python可被粗略地分類為手稿語言,Python的支持者較喜歡稱它為一種高階動態語言,常像「膠水」一樣被用來連接軟體組件,已經顯著的區別於Unix shell、Windows PowerShell這樣的語言。基於Python的xonsh,是跨平台的、青睞Unix的shell語言和命令列介面[261]。
一些Linux發行版,使用Python語言編寫安裝器,比如Ubuntu的Ubiquity和Fedora的Anaconda;或使用它編寫軟體包管理系統,比如Gentoo的Portage。下面舉例使用Python編寫或將它作為嵌入式指令碼的一些應用程式:
- IPython:以多種程式語言進行互動式計算的命令shell和Jupyter的核心,最初為Python開發,它提供了內省、富媒體、shell語法、tab補全和歷史。
- Conda:跨平台的、語言無關的二進制包管理器,它被Python的Anaconda發行版採用。
- Orange:基於scikit-learn和pandas的開源機器學習和資料視覺化軟體,利用了PyQt5和基於Blink的PyQtWebEngine,通過廣大多樣的工具箱來建造資料分析工作流程[262],由盧布林雅那大學開發。
- SageMath:涵蓋許多數學功能的應用軟體,它建造在NumPy、SciPy、matplotlib、SymPy、Maxima、GAP、FLINT、R等開源軟體套件之上。
- MayaVi:基於VTK的應用程式和庫,用於互動式科學資料視覺化和採用Python的3D繪圖[263]。
- Pitivi:用Python開發的基於GStreamer的影片編輯軟體。
- Blender:開源3D繪圖軟體,使用Python作為建模工具與GUI語言。
- Inkscape:開源的SVG向量圖形編輯器,使用Python用於外掛程式。
經由Python開發了眾多的人工智慧模型和作為其支撐的軟體庫:
- Ray:對人工智慧及Python應用的執行規模進行伸縮的統一框架[264],由Anyscale公司開發。它構成自一個核心的分散式執行時系統,和加速機器學習工作負載的AI軟體庫。
- Kornia:基於PyTorch的可微分電腦視覺軟體庫[265]。
- spaCy:用Python和Cython開發的工業級實力的自然語言處理軟體庫[266]。
- OpenNMT:神經機器翻譯和神經序列學習的開源生態系統[267]。
- Stable Diffusion:用Python開發的深度學習文字到圖像生成模型[268],基於了CUDA、PyTorch、VAE、U-Net和OpenAI的CLIP[269],其程式碼和模型權重已公開發布,可以在大多數配備有適度GPU的消費類電腦硬體上執行。
- Transformers:為下載和訓練前沿的預訓練模型提供API和工具[270],由Hugging Face開發,支援在PyTorch、TensorFlow和JAX之間的框架互操作性。
- Gradio:它是一個Python庫,允許快速建立和分享用於機器學習模型、API或任何任意Python函式的Web應用程式。使用Gradio,可以構建互動式使用者介面,與各種機器學習框架相容。還可以使用Gradio以互動方式偵錯模型、從使用者取得回饋,並通過自動生成的可共享連結輕鬆部署模型。[271][272]
- LangChain:它是一個應用框架,旨在簡化使用大型語言模型的應用程式。作為一個語言模型整合框架,LangChain的用例包括文件分析和總結摘要, 程式碼分析和聊天機器人。[273] LangChain提供了一個標準介面,用於將不同的語言模型(LLM)連接在一起,以及與其他工具和資料來源的整合。
自從2003年,Python始終排行於TIOBE程式社群索引前十最流行程式語言,在2021年10月它首次達到了第一名最流行語言(居於C和Java之前),並被選為2007年、2010年、2018年、2020年、2021年和2024年的年度程式語言[43]。它有如下著名的社群:
影響的語言
Python的設計和哲學已經影響了很多其他程式語言:
- Boo:使用了縮排、類似的語法和類似的對象模型[23]。
- Cobra:使用了縮排和類似的語法[24]。
- CoffeeScript:有受Python啟發的語法[25]。
- ECMAScript/JavaScript:從Python借鑑了迭代器和生成器。
- GDScript:內建於Godot遊戲引擎的非常類似Python的手稿語言[26]。
- Genie:基於Vala編譯器的具有近似Python語法的語言。
- Go:其設計原則受到了Python的可讀性與易用性的啟發[27],享有相同風格的陣列分片語法。
- Groovy:受到Python等動態型別語言的影響[28]。
- Julia:在表達進階數值計算的方式和支援通用程式上借鑑了Python等語言[31]。
- Kotlin:融合了Python和Java特徵,極小化了樣板程式碼而增加了開發效率[32]。
- Nim:使用縮排和類似的語法[34]。
- Ruby:主要從Python等語言中借鑑了特徵[35]。
- Starlark:用在Bazel軟體中有受Python啟發語法的語言[36]。
- Snek:受Python啟發的微小的可嵌入式語言,其目標處理器僅有數以kB計的快閃記憶體和靜態主記憶體[275]。
- Swift:有受Python啟發的語法[37]。
在Python基礎上開發的程式語言有:
範例與注釋
- 縮排範例:
def is_even(a: int) -> bool: """确定数a是否是偶数.""" if a % 2 == 0: print('偶数!') return True print('奇数!') return False # 参数比后续部份多一层缩进 def long_function_name( var_one, var_two, var_three, var_four): # 可选的圆括号内后续行多一层缩进 if (this_is_first_thing and that_is_second_thing): do_something() # 可选的圆括号内后续行不额外缩进 elif (this_is_third_thing and that_is_fourth_thing): do_something_different() # 参数相对行首缩进一层 spam = long_function_name( arg_one, arg_two, arg_three, arg_four) # 参数按开括号界定垂直对齐 eggs = long_function_name(arg_one, arg_two, arg_three, arg_four) # 可选的闭括号位置 my_list = [ 1, 2, 3, 4, 5, 6, ] # 可选的闭括号位置 my_set = { 1, 2, 3, 4, 5, 6, }
- 產生素數的惰性生成器的範例:
from itertools import count def generate_primes(stop_at=0): if stop_at != 1: primes = [2] yield 2 for n in count(3, 2): if 0 < stop_at < n: return # 引发StopIteration例外 composite = False for p in primes: if not n % p: composite = True break elif p ** 2 > n: break if not composite: primes.append(n) yield n
上述函式的隱式迭代用例:
for i in generate_primes(): # 迭代于100以内所有素数上 if i > 100: break print(i)
在生成器表達式中使用上述函式,定義了一個惰性的、巨大而並非無限的搜集的範例:
from itertools import islice primes_under_million = (i for i in generate_primes() if i < 1000000) two_thousandth_prime = islice(primes_under_million, 1999, 2000) print(next(two_thousandth_prime))
- 下面的範例用生成器類比協程[112]:
def produce(n): try: for item in range(n): print(f'producing item {item} ->') yield item except GeneratorExit: return def consume(): item = None try: while True: item = yield item print(f'consuming item {item} <-') except GeneratorExit: return def main(): r = [] t1 = produce(10) t2 = consume() try: next(t2) while True: p = next(t1) r += [t2.send(p)] except StopIteration: t2.close() print(f'result items: {r}') main()
- 原生的協程範例:
import asyncio import random async def produce(queue, n): for item in range(n): # 生产一个项目,使用sleep模拟I/O操作 print(f'producing item {item} ->') await asyncio.sleep(random.random()) # 将项目放入队列 await queue.put(item) # 指示生产完毕 await queue.put(None) async def consume(queue): while True: # 等待来自生产者的项目 item = await queue.get() if item is None: break # 消费这个项目,使用sleep模拟I/O操作 print(f'consuming item {item} <-') await asyncio.sleep(random.random()) async def main(): queue = asyncio.Queue() task1 = asyncio.create_task(produce(queue, 10)) task2 = asyncio.create_task(consume(queue)) await task1 await task2 asyncio.run(main())
- 使用
with
將檔案作為資源來管理的範例:from contextlib import contextmanager @contextmanager def opened(filename, mode="r"): try: f = open(filename, mode) except IOError as error: print(error) yield None else: try: yield f finally: f.close() with opened("aFileName", mode="w") as f: try: f.write(could_make_error()) # 不存在could_make_error()则产生错误 except AttributeError: print("不能打开文件") except: # 捕获所有例外 print("未预期的错误") else: # 在没有出现例外时执行 print("文件写入完全成功")
- 除了在塊中出現的每個賦值語句或匯入語句之外,下列構造也繫結名字:給函式的形式參數、類別定義、函式定義、賦值表達式、在
for
語句頭部中和各種as
關鍵字之後的識別碼目標(target),as
關鍵字出現在import
語句、with
語句、except
子句、except*
子句和結構式模式匹配的as
模式之中。 - 完整的Python程式,在一個極小初始化的環境中執行:所有內建和標準模組均可獲得,但除了
sys
(各種系統服務)、builtins
(內建函式、例外和None
)和__main__
之外都未被初始化。__main__
用來為完整程式的執行提供局部和全域名字。當直譯器被呼叫在互動模態下的時候,它一次一個的讀取並執行語句;初始環境同於完整程式,每個語句都在__main__
的名字空間中執行。
頂層程式碼是啟動執行的首個使用者指定Python模組。__main__
是頂層程式碼執行所在的環境。從命令列使用-m
參數,作為頂層指令碼執行的模組(作為模組__main__
)是塊。此時__name__
變數被設定為"__main__"
,籍此可在這個模組中增加直接執行時候執行的程式碼[116][122]。 - 局部變數範例:
>>> def spam(): ... print(a) ... >>> a = 10 >>> spam() 10 >>> def spam(): ... a = 100 ... print(a) ... >>> spam() 100 >>> a 10 >>> def spam(): ... a *= 10 ... print(a) ... >>> spam() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in spam UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
- 非局部變數範例:
>>> def spam(): ... def eggs(): ... nonlocal a ... a *= 10 ... print(a) ... a = 10 ... eggs() ... >>> spam() 100 >>> def spam(): ... def eggs(): ... nonlocal a ... a *= 10 ... print(a) ... global a ... eggs() ... File "<stdin>", line 3 SyntaxError: no binding for nonlocal 'a' found
- 全域變數範例:
>>> def spam(): ... global a ... a *= 10 ... print(a) ... >>> a = 10 >>> spam() 100 >>> a 100 >>> def spam(): ... def eggs(): ... print(a) ... global a ... eggs() ... >>> a = 10 >>> spam() 10 >>> def spam(): ... def eggs(): ... a *= 10 ... print(a) ... global a ... eggs() ... >>> spam() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in spam File "<stdin>", line 3, in eggs UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
- 通過表達式列表建立元組範例:
a_tuple = 1, 2, 3, 'four'
通過列表展示建立列表範例:
a_list = [1, 2, 3, 'a dog']
通過字典展示建立字典範例:
a_dictionary = {'key 1': 'value 1', 2: 3, 4: []}
通過集合展示建立集合範例:
some_set = {0, (), False}
- 列表推導式範例:
>>> [x + 3 for x in range(4)] [3, 4, 5, 6]
使用列表推導式可以優雅的將快速排序演算法表達為:
def qsort(L): if L == []: return [] pivot = L[0] return (qsort([x for x in L[1:] if x < pivot]) + [pivot] + qsort([x for x in L[1:] if x >= pivot]))
生成器表達式範例:
>>> sum(x * x for x in range(10)) 285 >>> dict((n, n*n) for n in range(5)) {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} >>> set(n*n for n in range(5)) {0, 1, 4, 9, 16}
字典推導式範例:
>>> {x: x + 3 for x in range(4)} {0: 3, 1: 4, 2: 5, 3: 6}
集合推導式範例:
>>> {x + 3 for x in range(4)} {3, 4, 5, 6}
- 可迭代解包和字典解包範例:
>>> a = [1, 2, 3]; b = [4, 5] >>> c = [*a, b] >>> c [1, 2, 3, [4, 5]] >>> d = {*a, *b} >>> d {1, 2, 3, 4, 5} >>> e = (*a, *b) >>> e (1, 2, 3, 4, 5) >>> f = {'as':1, 'bs':2 }; g = {'cs':3, 'ds':4} >>> h = {**f, **g} >>> h {'as': 1, 'bs': 2, 'cs': 3, 'ds': 4}
- 列表分片範例:
>>> nums = [0, 1, 2, 3, 4, 5, 6] >>> nums[2:5] #从下标2的元素剪切直到下标5之前的元素 [2, 3, 4] >>> nums[1:] #从下标1的元素剪切直到末位元素 [1, 2, 3, 4, 5, 6] >>> nums[:-3] #从首位元素剪切直到倒数第3个元素之前的元素 [0, 1, 2, 3] >>> nums[:] #复制所有元素 [0, 1, 2, 3, 4, 5, 6] >>> nums[::-1] #反转所有元素 [6, 5, 4, 3, 2, 1, 0] >>> nums[1:5:2] #从下标1的元素剪切直到下标5之前的元素且步长为2 [1, 3]
- 兩個類及元類等的實例關係(藍色連接)與繼承關係(綠色連接)示意圖:
r = object c = type class M(c): pass class A(metaclass=M): pass class B(A): pass b = B()
>>> type(b) <class '__main__.B'> >>> print(type(B), B.__bases__) <class '__main__.M'> (<class '__main__.A'>,) >>> print(type(A), A.__bases__) <class '__main__.M'> (<class 'object'>,) >>> print(type(M), M.__bases__) <class 'type'> (<class 'type'>,) >>> print(type(c), c.__bases__) <class 'type'> (<class 'object'>,) >>> print(type(r), r.__bases__) <class 'type'> ()
- 詞法閉包的例子:
def f(x): def g(y): return x + y return g # 返回一个闭包。 h = lambda x: lambda y: x + y # 将指定闭包赋值给变量。 a = f(1) b = h(1) c = f(2) # 使用存储在变量中的闭包。 assert a(5) == 6 assert b(5) == 6 assert c(5) == 7 # 使用闭包而不事先把它们绑定到变量。 assert f(1)(5) == 6 # f(1)是个闭包。 assert h(1)(5) == 6 # h(1)是个闭包。 assert f(2)(5) == 7 # f(2)是个闭包。
- 函式的形實參數二者結合範例。例如:
>>> def spam(a): ... a.append('LovelySpam') ... >>> def eggs(b): ... b=100 #实际上是重新绑定了另一个整型对象100 ... >>> a=[] >>> b=10 >>> spam(a) >>> eggs(b) >>> print(a) ['LovelySpam'] >>> print(b) 10
- 當形式參數的預設值是可變對象比如列表或字典的時候,如果這個函式修改了這個對象,則這個形式參數的預設值就在實效上被修改了。比如:
>>> def f(a, L=[]): ... L.append(a) ... return L ... >>> print(f(1)) [1] >>> print(f(2)) [1, 2] >>> print(f(0, [])) [0] >>> print(f(3)) [1, 2, 3]
這通常不是所預期的效果。一種解決辦法是使用
None
作為預設值,並在函式主體中顯式的測試它:def f(a, L=None): if L is None: L = [] L.append(a) return L
- 函式的形式參數預設值的定義範例:
>>> from inspect import getfullargspec >>> def func(p1, /, p2, p3="x", *, p4): pass ... >>> getfullargspec(func) FullArgSpec(args=['p1', 'p2', 'p3'], varargs=None, varkw=None, defaults=('x',), kwonlyargs=['p4'], kwonlydefaults=None, annotations={})
- 函式的可變參數的定義範例:
>>> from inspect import getfullargspec >>> def func(p1, /, p2, *args, p3, **kwargs): pass ... >>> getfullargspec(func) FullArgSpec(args=['p1', 'p2'], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=['p3'], kwonlydefaults=None, annotations={})
- 定義修飾器的範例:
def viking_chorus(func): def wrapper(*args, **kwargs): for i in range(3): func(*args, **kwargs) return wrapper
呼叫修飾器的範例:
@viking_chorus def menu_item(*args): print(", ".join(args)+", and spam")
它等價於:
def menu_item(*args): print(", ".join(args)+", and spam") menu_item = viking_chorus(menu_item)
viking_chorus
修飾後的menu_item
將原來定義執行3次:>>> menu_item("egg","bacon") egg, bacon, and spam egg, bacon, and spam egg, bacon, and spam
- 修飾器工廠範例,這裡的
favourite_colour
接受一個實際參數,並返回一個修飾器:def favourite_colour(colour): def decorator(func): def wrapper(*args, **kwargs): print(f"My favourite colour is {colour}.") func(*args, **kwargs) return wrapper return decorator def invincible(func): def wrapper(*args, **kwargs): print("I'm invincible!") func(*args, **kwargs) return wrapper
使用毗連的修飾詞連結修飾器範例:
@invincible @favourite_colour("blue") def black_knight(): print("None shall pass.")
它等價於:
black_knight = invincible(favourite_colour("blue")(black_knight))
black_knight()結果為:
>>> black_knight() I'm invincible! My favourite colour is blue. None shall pass.
- 對象的方法範例:
>>> class Fish(object): ... hungry = True ... def eat(self, food=None): ... if food is not None: ... self.hungry = False ... ... def status(self): ... print("Hungray!" if self.hungry else "Not hungray!") ... >>> e = Fish() >>> Fish.hungry = False >>> e.hungry False >>> Fish.hungry = True >>> e.hungry True >>> e.__dict__ {} >>> status(e) Hungray! >>> Fish.status = status >>> type(Fish.status) <class 'function'> >>> type(e.status) <class 'method'> >>> e.status() Hungray! >>> e.eat("earthworm") >>> e.__dict__ {'hungry': False} >>> e.status() Not hungray! >>> Fish.hungry True
- 特殊方法
__init__
和類別變數__slots__
(槽)範例:>>> class Bird(object): ... __slots__ = ['hungry'] ... def __init__(self, *args, **kwargs): ... self.hungry = True ... def eat(self, food=None): ... if food is not None: ... self.hungry = False ... def status(self): ... print("Hungray!" if self.hungry else "Not hungray!") ... >>> Bird.hungry <member 'hungry' of 'Bird' objects> >>> type(Bird.hungry) <class 'member_descriptor'> >>> f = Bird() >>> f.status() Hungray! >>> f.eat("mealworm") >>> f.status() Not hungray! >>> assert '__dict__' not in dir(Bird)
- 在類中採用資料描述器的範例:
>>> from weakref import WeakKeyDictionary >>> class RevealAccess(): ... """ 在存取时披露提示消息的数据描述器 ... """ ... def __init__(self, default=None): ... self.default = default ... self.dict = WeakKeyDictionary() ... def __get__(self, obj, objtype=None): ... print('Retrieving') ... return (self.dict[obj] if obj in self.dict ... else self.default) ... def __set__(self, obj, val): ... print('Updating') ... self.dict[obj] = val ... >>> class MyClass(): ... x = RevealAccess(10) ... >>> a = MyClass() >>> a.x Retrieving 10 >>> a.x = 20 Updating >>> a.x Retrieving 20 >>> b = MyClass() >>> b.x Retrieving 10
- 在類中呼叫
property()
的例子:>>> class C(): ... def __init__(self, *args, **kwargs): ... self.__x = None ... def getx(self): ... return self.__x ... def setx(self, value): ... self.__x = value ... def delx(self): ... del self.__x ... x = property(getx, setx, delx, "I'm the 'x' property.") ... >>> c = C() >>> vars(c) {'_C__x': None} >>> {*C.__dict__} {'__module__', '__firstlineno__', '__init__', 'getx', '__doc__', '__static_attributes__', 'delx', '__dict__', '__weakref__', 'setx', 'x'}
上述程式碼可以採用修飾詞進一步的書寫為:
>>> class C(): ... def __init__(self, *args, **kwargs): ... self.__x = None ... @property ... def x(self): ... """I'm the 'x' property.""" ... return self.__x ... @x.setter ... def x(self, value): ... self.__x = value ... @x.deleter ... def x(self): ... del self.__x ... >>> c = C() >>> vars(c) {'_C__x': None} >>> {*C.__dict__} {'__module__', '__firstlineno__', '__init__', '__doc__', '__static_attributes__', '__dict__', '__weakref__', 'x'}
- 類別方法、靜態方法
__new__
(它是特殊情況而不需要加以修飾)、特殊方法__call__
、__len__
、__getitem__
、__setitem__
和弱參照集合範例:>>> from weakref import WeakSet ... class D(): ... __template = {} ... __obj_set = WeakSet() ... def __new__(cls, *args, **kwargs): ... obj = super().__new__(cls) ... cls.__obj_set.add(obj) ... return obj ... @classmethod ... def load(cls, dict): ... cls.__template |= dict ... @classmethod ... def create(cls, *args, **kwargs): ... return cls(cls.__template, *args, **kwargs) ... @classmethod ... def count(cls): ... return len(cls.__obj_set) ... @classmethod ... def contains(cls, obj): ... return obj in cls.__obj_set ... def __init__(self, dict={}, /, *args, **kwargs): ... self.__dict__ |= dict ... self.__dict__ |= kwargs ... def __call__(self, *args, **kwargs): ... self.__dict__ |= kwargs ... return self.__dict__.copy() ... def __len__(self): ... return len(self.__dict__) ... def __getitem__(self, key): ... return self.__dict__[key] ... def __setitem__(self, key, value): ... self.__dict__[key] = value ... >>> a = {'ak': 1, 'bk': 2, 'ck': 3} >>> d = D(a, dk=4) >>> d() {'ak': 1, 'bk': 2, 'ck': 3, 'dk': 4} >>> D.load(a) >>> e = D.create(ck=4) >>> e() {'ak': 1, 'bk': 2, 'ck': 4} >>> f = D(ak=1, bk=2) >>> f(ck=3) {'ak': 1, 'bk': 2, 'ck': 3} >>> f['ak'] 1 >>> f['ak'] = 5 >>> f() {'ak': 5, 'bk': 2, 'ck': 3} >>> len(f) 3 >>> D.count() 3 >>> del f >>> D.count() 2 >>> d.__weakref__ <weakref at 0x72652697ede0; to 'D' at 0x72652713b230> >>> D.contains(d) True >>> D.contains(1) False
- 類別方法
__init_subclass__
和在子類中用內建函式super()
呼叫超類別的實例方法和類別方法的例子:>>> class Thought(object): ... __cls_descr = "Thought类型" ... @classmethod ... def descript(cls): ... return cls.__cls_descr ... def __init_subclass__(cls): ... cls.__cls_descr = "Thought类型的子类型" ... def __init__(self, *args, **kwargs): ... self.idea = "我感觉自己斜停在了平行宇宙里。" ... print(f"我是{type(self).descript()}的新对象!") ... def message(self, *args): ... print("\n".join([self.idea] + [*args])) ... ... class Advice(Thought): ... @classmethod ... def descript(cls): ... return super().descript() + "Advice类型" ... def message(self): ... super().message("警告:日历中的日期比实际显示的更近!") ... >>> t = Thought() 我是Thought类型的新对象! >>> t.message() 我感觉自己斜停在了平行宇宙里。 >>> a = Advice() 我是Thought类型的子类型Advice类型的新对象! >>> a.message() 我感觉自己斜停在了平行宇宙里。 警告:日历中的日期比实际显示的更近! >>> super(Advice, a).message() 我感觉自己斜停在了平行宇宙里。 >>> Advice.super = super(Advice) >>> a.super.message() 我感觉自己斜停在了平行宇宙里。 >>> [*super.__dict__] ['__new__', '__repr__', '__getattribute__', '__get__', '__init__', '__thisclass__', '__self__', '__self_class__', '__doc__'] >>> super(Advice).__thisclass__ <class '__main__.Advice'> >>> assert super(Advice).__self__ is None >>> assert super(Advice).__self_class__ is None >>> super(Advice, a).__self__ <__main__.Advice object at 0x754299f19940> >>> super(Advice, a).__self_class__ <class '__main__.Advice'> >>> super(Thought, Advice).__thisclass__ <class '__main__.Thought'> >>> super(Thought, Advice).__self__ <class '__main__.Advice'> >>> super(Thought, Advice).__self_class__ <class '__main__.Advice'>
參照
延伸閱讀
參閲
外部連接
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads