Remove ads
通用高級編程語言 来自维基百科,自由的百科全书
Python(英式發音:/ˈpaɪθən/;美式發音:/ˈpaɪθɑːn/),是一種廣泛使用的直譯式、進階和通用的程式語言。Python支援多種程式設計範式,包括結構化、程序式、反射式、物件導向和函數式程式設計。它擁有動態型別系統和垃圾回收功能,能夠自動管理主記憶體使用,並且其本身擁有一個巨大而廣泛的標準庫。它的語言結構以及物件導向的方法,旨在幫助程式設計師為小型的和大型的專案編寫邏輯清晰的程式碼。
編程範型 | 多範式:程序式、結構化、模組化、反射式、物件導向、函數式 |
---|---|
設計者 | 吉多·范羅蘇姆 |
實作者 | Python軟體基金會 |
釋出時間 | 1991年[1] |
目前版本 |
|
型態系統 | 鴨子型別[3]、動態、強型別[4]、漸進(自從3.5)[5] |
作業系統 | 跨平臺 |
特許條款 | Python軟體基金會特許條款 |
副檔名 | .py、.pyi、.pyc、.pyd、.pyo(3.5之前)[6]、.pyw、.pyz(自從3.5)[7] |
網站 | www |
主要實作產品 | |
CPython、PyPy、Stackless Python、MicroPython、CircuitPython、IronPython、Jython | |
衍生副語言 | |
Cython、RPython | |
啟發語言 | |
ABC[8]、ALGOL 68[9]、APL[10]、C[11]、C++[12]、CLU[13]、Dylan[14]、Haskell[15]、Icon[16]、Java[17]、Lisp[18]、Modula-3[12]、Perl[19]、Standard ML[10] | |
影響語言 | |
Boo、Cobra、CoffeeScript[20]、D、F#、GDScript[21]、Genie[22]、Go[23]、Groovy、JavaScript[24][25]、Julia[26]、Mojo[27]、Nim、Ruby[28]、Starlark[29]、Swift[30] | |
吉多·范羅蘇姆於1980年代後期開始研發Python,作為ABC語言的後繼者[16],它也可以被視為採用了叫做M-表達式的中綴表示法的一種LISP方言[31]。吉多·范羅蘇姆於1991年首次釋出 Python 0.9.0[32]。Python 2.0於2000 年釋出並引入了新功能。Python 3.0於2008年釋出,它是該語言的主要修訂版,並非完全向下相容。Python 2於2020年隨2.7.18版停止支援[33]。
Python的設計哲學,強調程式碼的可讀性和簡潔的語法,尤其是使用空格縮排來劃分程式碼塊。相比於C語言或Java,Python讓開發者能夠用更少的代碼表達想法。
Python直譯器本身幾乎可以在所有的作業系統中執行,它的官方直譯器CPython是用C語言編寫的。Python是一個由社群驅動的自由軟體,目前由Python軟體基金會管理。Python是最受歡迎的程式語言之一[34][35][36][37]。
Python的創始人吉多·范羅蘇姆,在1982年至1995年間,參與了荷蘭數學和電腦科學研究學會多個專案的工作[38]。1989年的聖誕節期間,他決心開發一個新的指令碼解釋程式,作為ABC語言的繼承者,並且用它替代Unix shell和C語言來進行系統管理[16],擔負與Amoeba作業系統[39]之間的互動操作並進行例外處理[8]。他是BBC電視劇《Monty Python的飛行馬戲團》的愛好者,所以選取了Python作為這個程式語言的名字[40]。范羅蘇姆作為Python的主要開發者,獨自擔負這個專案的發展決策者職責,直到2018年7月12日,他宣佈從終身仁慈獨裁者(BDFL)的職位上「永久休假」[41][42]。他在2019年1月至11月參與了第一屆五人掌控委員會繼續領導專案發展[43][44]。
在1991年2月,范羅蘇姆在alt.sources上釋出了最初程式碼(標記為版本0.9.0)[1],這時就已經存在了帶繼承的類、例外處理、函數和核心類型list
、dict
、str
等。在這個最初發行中就有了從Modula-3引進的模組系統[45],和例外處理機制[8]。在1994年1月,Python達到了版本1.0[46],其主要新特徵是由Amrit Prem提供的函數式程式設計工具lambda
、map
、filter
和reduce
[47]。受Modula-3啟發,Python 1.1介入了預設參數值,Python 1.3介入了關鍵字參數。Python 1.4介入了對複數的內建支援,還包含了採取名字修飾的一種基本形式的數據隱藏[48]。
在2000年10月,Python 2.0發佈,它從函數式程式設計語言Haskell中引進了列表推導式,並且支援了Unicode,還向垃圾回收系統增加了環檢測演算法[49]。Python 2.1支援了靜態巢狀作用域和閉包[50]。Python 2.2進行了重大革新,將Python中用C語言寫成的類型,和用Python語言寫成的類,統一成在同一個層級中,使得Python的對象模型成為純粹而一致的對象模型[51];還介入了迭代器[52],受CLU和Icon啟發的生成器[53],和描述器協定[54]。Python 2.3介入了從Dylan引進的方法決定次序[14]。Python 2.4介入了集合類型,和函數修飾器[55]。Python 2.5介入了with
陳述式[56],並在官方實現中介入了抽象語法樹[57]。
在2008年12月,Python 3.0發佈,它對語言做了較大修訂而不能完全後向相容[58],儘管提供了進行自動轉換2to3
實用工具,仍有大量現存程式碼不能移植,故而Python 2.7的產品壽命結束延期至2020年元旦。Python 3.4介入了非同步I/O模組[59]。Python 3.5介入了類型提示[60],和採用async/await語法的協程[61]。Python 3.8介入了賦值表達式[62][63]。
在2020年10月,Python 3.9介入了內建的針對容器類的泛化別名(types.GenericAlias
)類型[64],並在官方實現中介入了新的語法解析器[65]。Python 3.10介入了結構式模式匹配[66],和內建的聯合類型(types.UnionType
)[67]。Python 3.11對官方實現進行了最佳化提速[68]。Python 3.12介入了類型參數語法和type
陳述式[69],並廢棄或移除了一些過時的模組和功能。Python 3.13介入了新的互動式直譯器,並實驗性的支援了在自由線程模態下執行和即時編譯器[70]。
每個版本首次發行後,享有2年的完全支援,隨後是3年的安全支援。當前只有Python 3的穩定版本3.12與3.13正在被完全支援,但仍提供對3.9、3.10和3.11版本的安全性修正[71]。
在2024年12月,活躍的Python核心開發者,選舉Pablo Galindo Salgado、Barry Warsaw、Emily Morehouse、Gregory P. Smith和Donghee Na,為2025年度「掌控委員會」的五位成員來領導這個專案[72]。
Python是多範式程式語言。它完全支援結構化程式和物件導向程式設計,還有很多特徵支援函數式程式設計和元程式設計比如元對象協定(元類和魔術方法[73])。通過擴充還可以支援很多範式,包括面向方面程式[74]、契約式設計[75]和邏輯程式[76]。
Python使用動態型別,在主記憶體管理上採用的垃圾回收器基於了參照計數[77],並且結合了檢測環參照的分代垃圾回收最佳化[78]。它的特徵還有動態名字解析(後期繫結),即在程式執行期間繫結方法和變數的名字。
Python對遵循LISP傳統的函數式程式設計提供了有限的支援[79],它提供了 map
、filter
和reduce
函數[80];列表推導式、字典、集合和生成器表達式。標準庫中的模組functools
和itertools
,實現了從Haskell和Standard ML借鑑來的函數式工具[81]。
Python的設計理念是「優雅」、「明確」、「簡單」,它的一些重要準則被合稱為「Python之禪」。在Python解釋器內運行import this
可以獲得完整的列表,下面舉出其中首要:
Python開發者的方法論是「用一種方法,最好是只有一種方法來做一件事」,顯著不同於以Perl語言為代表的「不止一種方法去做一件事」風格。Python開發者在設計語言時,如果面臨多種選擇,一般會選擇明確沒有或者很少有歧義的語法。
范羅蘇姆認為ABC語言非常優美和強大,它沒有取得成功的原因是不開放造成的[82],故而將Python本身設計為可擴充的[83]。Python並不把所有的特性和功能都整合到語言核心,而是提供了豐富的API和工具,以便程式設計師能夠輕鬆地使用Python、C語言、Cython來編寫擴充模組。Python還可以通過外界函數介面如標準庫中的ctypes等,來提供C語言相容資料類型,並訪問動態連結庫或共用庫中的函數[84],從而對用其他語言編寫的程式進行整合和封裝。
在Python的官方實現CPython中,一般避開不成熟的或者對非重要部位的加快運行速度的優化。在某些對運行速度要求很高的情況,可以使用具備JIT技術的Python實現或安裝JIT擴充模組[85]。
Python為了讓程式碼具備高度的可閱讀性,在設計時盡量使用了其它語言常用的符號和英文單字。
Python支援使用反斜槓作為行接續符,將多個物理行合成為一個邏輯行[86]。在圓括號、方括號或花括號之中的表達式,可以分裂跨越多於一個物理行而不使用反斜槓,這被稱為「隱式行接續」[86]。註釋開始於並非字串文字一部份的一個井號#
,並結束於物理行結尾;註釋標示邏輯行的結束,除非已受制於隱式行接續規則;註釋在語法上被忽略[87]。
簡單陳述式包含在一個單一的邏輯行之內,Python支援使用分號作為分隔符,將多個簡單陳述式合併入語法意義上的一行之中[88]。
Python語法中的複合陳述式,包含(成組的)其他陳述式;它們以某種方式影響或控制這些其他陳述式的執行。Python的複合陳述式包含一個或多個子句(clause),子句構成自一個頭部(header)和一個套件(suite)。特定複合陳述式的子句頭部都在同樣的縮排層級上,每個子句頭部開始於一個唯一標識關鍵字,並結束於一個冒號。套件是這個子句所控制的一組陳述式,套件有兩種形式,可以是與頭部在同一行上的一個或多個由分號分隔的簡單陳述式,它們跟隨在這個頭部的冒號之後;或者是在後續諸行上的一個或多個縮排的陳述式,只有這種套件形式可以包含巢狀的複合陳述式[89]。
Python語言遵循越位規則,利用縮排來形成陳述式套件,即語法意義上的塊。連續諸行的縮排層級,被用來生成語法解析器才能見到的INDENT
和DEDENT
記號[90],二者的作用相當於C語言家族的花括號,或Pascal語言家族的關鍵字begin
和end
。增加縮排就生成INDENT
記號,減少縮排就生成DEDENT
記號。根據PEP 8的規定[91],使用4個空格來表示每級縮排。[a]
tab字元(從左至右)被替代為1至8個空格,使得直到tab之前的諸字元加上這些替代空格的字元總數,是8的倍數(這意圖同於Unix所用規則)。前導於第一個非空白字元的空格的總數,確定了這一行的縮排層級。縮排所用諸字元,不能使用反斜槓來拆分成多個物理行;直到第一個反斜槓之前的空白確定縮排層級。如果原始碼檔案混合了tab和空格,並且在這種方式下縮排的意義依賴於一個tab相當於多少個空格,則這種縮排因不一致性而被報錯並拒絕[92]。
Python有如下35個關鍵字;它們不能用作識別碼[93]:
|
|
|
|
|
|
|
內建常數True
、False
和None
於Python版本3.0中成為關鍵字,關鍵字nonlocal
介入於版本3.0[94],關鍵字async
和await
介入於版本3.5[95],並在版本3.7中成為正式關鍵字[96]。
在Python中,將只在特定上下文中保留的識別碼,稱為「軟關鍵字」[97]:
識別碼就是名字,在ASCII範圍內(U+0001..U+007F),可用於識別碼的字元為:大寫字母A
至Z
和小寫字母a
至z
,底線_
以及數字0
至9
,但首字不可以用數字。如下命名約定[98],是為「保留識別碼類」[99]:
_spam
(單底線開頭):弱「內部使用」標識。對於from M import *
,將不匯入所有以底線開頭的對象。spam_
(單底線結尾):為了避免與python關鍵字的命名衝突。__spam
(雙底線開頭):在命名一個類特性的時候,採用名字修飾,比如在類SpamEggs
內,__spam
將變成_SpamEggs__spam
[100]。__spam__
(雙底線開頭雙底線結尾):指那些包含在用戶控制的命名空間中的「魔術」方法或特性,比如__delattr__
、__dir__
、__doc__
、__getattribute__
、__init__
、__new__
、__repr__
、__setattr__
、__sizeof__
等。建議永遠不要將這樣的命名方式應用於自己的變數或函數。Python的陳述式包括簡單陳述式:
=
。賦值陳述式被用來將名字繫結(含重新繫結)到值,以及用來修改可變對象的特性或專案。
None
。global
陳述式,是在整個當前程式碼塊中成立的聲明,它意味着隨後列出的識別碼被直譯為全域變數。nonlocal
陳述式,導致隨後列出的識別碼,提及在除了全域作用域之外的最近包圍作用域中的先前繫結變數。type
陳述式,介入於版本3.12,聲明作為類型別名類型(typing.TypeAliasType
)的實例的一個類型別名。pass
陳述式,充當NOP,表示此行為空,不執行任何操作。assert
陳述式,用於程式調適階段時測試執行條件是否滿足。continue
陳述式,越過這次迭代並繼續進行下個專案。break
陳述式,從迴圈中跳出。return
陳述式,用來從函數返回值。當函數執行到return
陳述式時,它會停止執行並將指定的值返回給呼叫者。raise
陳述式,投擲一個例外。yield
陳述式,使用它從一個生成器中返回一個值。在版本2.5之前,資訊只能單向的從生成器傳遞出來。[c]
import
陳述式,匯入一個模組或包,它組合了兩種操作,尋找指名的模組,接着將找到的結果繫結到在局部作用域中的名字。匯入陳述式有三種形式(下述陳述式樣本中的方括號表示其中內容為可選的):
del
陳述式,遞歸的進行刪除。複合陳述式:
if
陳述式,當條件成立時執行陳述式套件。它經常包含elif
、else
子句。while
陳述式,當條件為真時,重複執行陳述式套件。for
陳述式,遍歷列表、字串、字典、集合等迭代器,依次處理迭代器中的每個元素。match
陳述式,用於模式匹配。try
陳述式,它經常包含except
、else
、finally
子句,處理在程式執行中出現的異常情況。Python支援並廣泛使用例外處理,作為檢測錯誤狀況和程式中其他「例外」事件的方式,並提倡在可能出現錯誤狀況的任何時候都使用例外。習慣上訪問一個檔案或資源不在使用之前進行測試,而是先行嘗試使用它,再擷取訪問被拒絕引發的例外。[e]Python 3.11介入了except*
子句[112]。with
陳述式,把一塊程式碼包裹在一個上下文管理器之內。它允許了資源取得即初始化(RAII)式行為,可替代常見的try
/finally
慣用法。Python使用with
陳述式處理資源[113],在進入一個作用域的時候呼叫一個函數,而在離開它的時候呼叫另一個函數,例如:在一塊程式碼執行之前取得一個鎖,並且在此後釋放這個鎖;或事先打開一個檔案,並且事後關閉它。[f]class
陳述式,是定義類的可執行陳述式。類的衍化列給出基礎類列表,沒有衍化列的類,預設繼承基礎類object
。類的套件接着在新的執行框架(frame)中執行,它使用新建的局部名字空間和原來的全域名字空間。當這個類套件完成執行之時,丟棄它的執行框架並儲存它的局部名字空間。一個類對象接着被建立,其基礎類採用衍化列,其特性字典採用儲存的局部名字空間。類名字接着在原來的局部名字空間中,被繫結到這個類對象。def
陳述式,是定義函數和方法的可執行陳述式。它的執行在當前局部名字空間中,將函數名字繫結到一個函數對象(對函數的可執行程式碼的包裝器)。這個函數對象包含到當前全域名字空間的參照,作為呼叫這個函數時使用的全域名字空間。async def
陳述式,用於協程函數定義。await
表達式、async for
陳述式和async with
陳述式,只能用在協程函數的主體中。[g]Python程式構造自程式碼塊。塊是作為一個單元執行的Python程式文字,模組、函數主體和類別定義都是塊。互動式鍵入的每個命令、指令碼檔案和指令碼命令都是程式碼塊。傳遞給內建函數eval()
和exec()
執行的字串是程式碼塊。
程式碼塊在執行框架(frame)中執行。框架包含一些用於偵錯的管理資訊,並確定在這個程式碼塊執行完成後,執行在何處以及如何繼續。名字空間是儲存變數的地方,它被實現為字典。有局部名字空間、全域空間即包含此程式碼塊的那個模組的名字空間,和內建名字空間即模組builtins
的名字空間;對象的方法是定義在類主體內的函數,它有着巢狀的名字空間。名字空間通過防止命名衝突而支援了模組性,還通過明晰了哪個模組實現了哪個函數而增進可讀性和可維護性。
模組是包含Python定義和陳述式的一個檔案,這個檔案名字是模組名字附加上字尾.py
;在一個模組中,模組的名字(作為字串)可獲得為全域變數__name__
的值[111]。包(package)是可以包含子模組或遞歸性的子包的模組。包在技術上是具有__path__
特性的Python模組。可以將包視為檔案系統上的目錄,而將模組視為這種目錄中的檔案,但是包和模組不必然源自檔案系統[114]。
完整的Python程式,在一個極小初始化的環境中執行:所有內建和標準模組均可獲得,但除了sys
(各種系統服務)、builtins
(內建函數、例外和None
)和__main__
之外都未被初始化。__main__
用來為完整程式的執行提供局部和全域名字。當直譯器被呼叫在互動模態下的時候,它一次一個的讀取並執行陳述式;初始環境同於完整程式,每個陳述式都在__main__
的名字空間中執行。
頂層程式碼是啟動執行的首個用戶指定Python模組。__main__
是頂層程式碼執行所在的環境。從命令列使用-m
參數,作為頂層指令碼執行的模組(作為模組__main__
)是程式碼塊。此時__name__
變數被設置為"__main__"
,籍此可在這個模組中增加直接執行時候執行的程式碼[111][115]。
名字是通用的參照持有者,它不關聯於一個固定的資料類型,但是,一個名字在給定時間,總是被繫結到有一個類型的某個對象上,這就是動態型別的特徵。名字的儲存位置不「包含」所指示的值,一個共同的值可以賦值給多個名字,一個名字在任何時候,都可以重新繫結到各種不同類型的對象上,包括字串、過程、具有數據和方法的複雜對象等。如果一個名字繫結在一個塊中,它是這個塊的局部變數,除非被聲明為nonlocal
或global
。如果一個名字繫結在模組層次,它是全域變數。模組程式碼塊的變數,既是局部的也是全域的。如果一個變數使用在一個程式碼塊中,卻不定義在這裏,它是自由變數[116]。
內建vars()
函數,返回一個模組、類、實例或任何具有字典特性__dict__
的對象的字典特性。內建globals()
函數,返回實現當前模組的名字空間的一個字典。內建locals()
函數,更新並返回表示當前局部符號表的一個字典。在函數塊中而非類塊中呼叫locals()
之時,它返回自由變數。在模組層級上,locals()
和globals()
返回同一個字典。內建dir()
函數,在無參數時,返回在當前局部作用域內的名字列表;在有一個參數時,嘗試返回這個對象的有效特性的列表。[117]
在Python中賦值所進行的操作,是將一個名字繫結為到一個分立的動態分配的對象的一個參照。除了在塊中出現的每個賦值陳述式或匯入陳述式之外,下列構造也繫結名字:給函數的形式參數、類別定義、函數定義、賦值表達式、在for
陳述式頭部中和各種as
關鍵字之後的識別碼目標(target),as
關鍵字出現在import
陳述式、with
陳述式、except
子句、except*
子句和結構式模式匹配的as
模式之中。
作用域定義一個名字在一個塊中的可見性。如果一個局部變數被定義在一個塊中,它的作用域包括這個塊。如果這個定義出現在一個函數塊中,作用域擴充到在所界定作用域內包含的任何塊,除非所包含的塊為這個名字介入了不同的繫結。當一個名字在一個程式碼塊之中使用,它採用最近包圍作用域來解析。對一個程式碼塊可見的所有這種作用域的集合,叫做這個這個塊的「環境」[116]。
如果一個名字繫結在一個塊中,並且在其中於繫結之前就被使用,會導致一個錯誤。[h]
如果global
陳述式出現在一個塊之中,在這個陳述式中指定的所有名字,提及在頂層名字空間中這些名字的繫結。名字在頂層名字空間解析,首先尋找全域名字空間,未果尋找內建名字空間。global
陳述式與在同一個塊中的名字繫結運算有同樣的作用域。如果一個自由變數的最近包圍作用域包含針對它的global
陳述式,這個自由變數被當作全域的[116]。[i]
當一個函數或類的定義被巢狀到其他函數的定義之內,它的非局部作用域就是這個包圍函數的局部作用域。nonlocal
陳述式導致其列出的識別碼,提及在非局部作用域內先前繫結的名字(即非局部變數)[116]。[j]
Python中很多表達式與C語言和java類似,而另一些則與之不同。
+
、減法-
、乘法*
和取模%
是與C語言和java相同的,但是除法的行為不同。在Python中有兩種除法,它們是下取整除法(或整數除法)//
和浮點除法/
。Python增加了指數算符**
。自從Python 3.5,介入了矩陣乘法算符@
[118],它已經用於了NumPy庫[119]。&
與(AND),|
或(OR),~
非(NOT),^
異或(XOR),>>
右移, <<
左移。>
,小於<
,等於==
,不等於!=
,小於等於<=
,大於等於 >=
。==
按值比較。Python的is
、is not
算符可以用來比較對象的同一性(按參照比較),也就是比較兩個變數是否參照了同一個對象。而in
、not in
用於判斷一個對象是否屬於另外一個對象。在Python中,比較是可以連結起來的[120],比如a < b < c
。,
分隔的一組表達式,叫做表達式列表。Python為構造列表、字典或集合,提供了叫做「顯示」的特殊語法,它們每個都有兩種方式:包容內容要麼顯式列舉出來;要麼通過一組迴圈和過濾指令計算而來,這叫做「推導式」。列表顯示是包圍在方括號中的可以為空的一系列表達式,一個例子列表可寫為[1,2,3]
。字典顯示是包圍在花括號中的可能為空的一系列的鍵/數據項對。集合顯示用花括號來指示,與字典顯示的區別是缺少分隔鍵與值的分號[121]。自從Python 3.5,增加了在表達式列表中的「可迭代解包」*
,和在字典顯示中的「字典解包」**
[122]。[k](1,2,3)
。元組不是圓括號形成的,而是使用逗號形成的,在沒有歧義的情況下,元組的圓括號是可選的。空的圓括號對產生空元組對象。使用序列串接算符+
來串接二個元組,產生包含給定元組二者的元素的一個新元組。a[索引]
,和分片表達式:a[开始:停止]
或a[开始:停止:步长]
。下標索引是基於零的,負數是相對於結尾的。分片範圍自從「開始」索引,直到但不包括「停止」索引。分片的第三個參數叫做「步長」(step)或「間隔」(stride),允許元素被跳過和用負數指示反向。分片索引可以省略,例如a[:]
,這返回整個列表的一個複本。[o]分片的每個元素都是淺層複製的。x if c else y
。意思是當c
為真時,表達式的值為x
,否則表達式的值為y
。 在運算元的次序上不同於很多其他語言中常見的c ? x : y
。:=
[62]。它將一個表達式賦值給一個識別碼,同時還返回這個表達式的值。賦值表達式在用作子表達式,即位於分片表達式、條件表達式、lambda
表達式、關鍵字參數中的表達式和推導式中的if
表達式之中,以及在assert
和with
陳述式之中的時候,必須圍繞着圓括號。在它們可以使用的所有其他地方,包括在if
和while
陳述式之中,都不要求圓括號[125]。Python中運算子具有優先級,下表中的運算子按照從最高到最低的次序列出。在相同儲存格中運算子具有相同的優先級,它們從左至右結合,除了指數表達式和條件表達式從右至左結合之外[126]:
運算子 | 描述 |
---|---|
(表达式...) ,[表达式...] ,{键: 值...} ,{表达式...} |
加圓括號表達式,列表顯示,字典顯示,集合顯示 |
x[索引] ,x[索引:索引] ,x(参数...) ,x.特性 |
下標,分片,呼叫,特性參照 |
await x |
await 表達式
|
** |
指數 |
+x ,-x ,~x |
取原數,相反數,逐位NOT |
* ,@ ,/ ,// ,% |
乘法,矩陣乘法,除法,下取整除法,餘數 |
+ ,- |
加法和減法 |
<< ,>> |
移位 |
& |
逐位AND |
^ |
逐位XOR |
| |
逐位OR |
in ,not in ,is ,is not ,< ,<= ,> ,>= ,!= ,== |
包含成員關係測試,同一測試,各種比較 |
not x |
布林NOT |
and |
布林AND |
or |
布林OR |
if – else |
條件表達式 |
lambda |
lambda表達式 |
:= |
賦值表達式 |
Python提供了序列串接算符+
和序列倍增算符*
[127]。自從Python 3.9,介入了字典合併算符|
和字典更新算符|=
[128]。
Python的文字序列類型,包括字串str
和位元組序列bytes
與bytearray
。字串文字有多種寫法,字串對象有一個內建格式算符%
:
'
或雙引號"
界定。不同於Unix shell、Perl和受Perl影響的語言,單引號和雙引號功能相同。這二種字串都使用反斜槓\
作為跳脫字元。r
或R
,這叫做原始字串。跳脫序列不被直譯,因此在文字反斜槓常見的地方很有用,比如正則表達式和Windows風格的路徑。[r]這種引述可比較於C#中的「@
引述」。%
,在功能上類同於C語言中的printf
格式化字串[130],例如"spam=%s eggs=%04d" % ("blah", 2)
,求值為'spam=blah eggs=0002'
。自從Python 3.0,str
類提供了可供替代的format()
方法[131],例如"spam={0} eggs={1:04d}".format("blah", 2)
。在Python 3.6中,提供了「格式化字串文字」或稱為「f字串」,它向字串文字字首上f
或F
[132],這是一種字串插值[133],例如x="blah"; y=2; f'spam={x} eggs={y:04d}'
。[t]在Python中,在表達式和陳述式之間的區別是嚴格強制性的,這對比於語言如Common Lisp、Scheme或Ruby。故而Python中個別構造存在功能重複,比如:列表推導式相當for
迴圈;條件表達式相當if
陳述式;內建函數eval()
相當exec()
,前者用於表達式,後者用於陳述式。
陳述式不能成為表達式的一部份,由於列表和其他推導式或lambda表達式,都是表達式,也就不能包含陳述式。這個限制的一個範例:賦值陳述式比如a = 1
,不能用作條件陳述式的條件判斷表達式的一部份;這能夠避免C語言程式中的一個常見錯誤,即在條件判斷時把等於算符==
誤寫為賦值算符=
,這不是預期程式碼卻在語法上有效而能通過編譯器檢查,在Python中這會導致一個語法錯誤。
Python的函數支援遞歸和閉包[u] ,及其他頭等函數特徵,但不支援函數多載。Python的函數作為頭等對象,具有和普通對象平等的地位。Python官方實現不提供尾呼叫最佳化或頭等續體,吉多·范羅蘇姆曾聲稱永遠都不會加以支援[134],但有第三方庫支援彈跳床[135]。
Python可以在函數定義時,於形式參數序列中,指定形式參數預設值,即以param=value
樣式進行一次性初始化。形式參數在初始化之後,保持既有繫結;函數的後續呼叫,可繼續對它進行訪問或變更。[v]為有預設值的形式參數提供實際參數,在函數呼叫時是可選的。
Python的函數實際參數與形式參數之間的結合,是傳遞「對象參照」,函數在被呼叫的時候,給函數呼叫的實際參數,被介入到一個局部符號表中,實際參數使用傳值呼叫來傳遞,而這個值總是對象參照,而非這個對象的值[136]。如果形式參數繫結到一個可變的對象,則通過形式參數對此對象內容的修改,在函數外也是可見的。如果形式參數繫結到一個不可變的對象,則通過形式參數是不能修改此對象內容,但可以把形式參數重新繫結到其它對象上,這並不影響函數外的對象的值。[w]
Python支援位置實際參數和關鍵字實際參數。函數呼叫時,實際參數可以如同C語言那樣,按照位置與形式參數匹配;也可以採用命名參數或稱為關鍵字實際參數,即kwarg=value
樣式的實際參數。使用不對應實際參數的特殊形式參數/
和*
,可以將參數序列分為三部份:唯位置參數[137]、可位置可關鍵字參數和唯關鍵字參數。有預設值的形式參數之後,不能跟隨無預設值的可位置形式參數。[x]在一個函數呼叫的實際參數序列中,關鍵字實際參數必須出現在位置實際參數之後。
在位置和關鍵字形式參數序列末尾,可以分別有*args
或**kwargs
這樣的形式參數,它們對應於在函數呼叫時提供的,超出形式參數序列規定而無所對應的多個實際參數;在形式參數名字前加一個*
號,該形式參數args
是tuple
類型,對應可變數目的位置實際參數;在形式參數名字前加**
號,該形式參數kwargs
是dict
類型,對應可變數目的關鍵字實際參數。[y]如果位置實際參數已經在一個序列類型如列表或元組的對象中,在參照它的變數前加一個*
號傳遞給函數,則其中所有元素解包為多個位置實際參數;如果關鍵字實際參數在字典中,則加**
號來傳遞給函數。
修飾器(decorator)可用來修改一個函數、方法或類別定義的任何可呼叫Python對象。將已定義的原來對象傳遞給修飾器,它返回一個修改後的對象,接着把它繫結到在定義中那個名字。Python修飾器部份受到Java註解的影響,而有類似的語法;修飾器語法是純粹的語法糖,使用@
作為關鍵字形成修飾詞。修飾器是一種形式的元程式設計,它們增強它們所修飾的函數或方法的行動。[z]
多個修飾器可以連結起來,通過在毗連的行上放置多個修飾詞,或者使用中間變數。[aa]
函數修飾器的正規用法包括:用來建立類別方法或靜態方法[55]、設置先決條件和後置條件、實現多方法、增加函數特性、跟蹤、同步[138];此外更遠大的用法包括:尾呼叫消除、記憶化[139]。
為了增強程式碼的可讀性,可以在函數後書寫「文件字串」(簡稱docstrings),用於直譯函數的作用、參數的類型與意義、返回值類型與取值範圍等。可以使用內建函數help()
,列印出函數的使用幫助。[ab]自從Python 3.0,函數可以對參數與返回值增加類型標註[140]。此特性可方便對原始碼進行更深入的分析。[ac]自從Python 3.5,開始支援類型提示[141]。
Python支援大多數物件導向程式設計技術。在Python中所有東西都是對象,包括類、函數、數和模組。它允許多型性,不只是在類層級之內,而且通過採用鴨子型別的方式[3]。任何對象可以用於任何類型,只要它有適當的方法和特性(attribute)就能工作。Python天然支援類的繼承包括多重繼承,為此採用C3線性化或方法決定次序(MRO)演算法,還支援混入。Python支援元類[142],自從Python 3.6,提供了客製化類建立的簡單機制[143]。
Python使用名字修飾,有限的支援私有變數。對象的(可寫)特性可以被提取為一個字典[144]。在Python中,不強制使用訪問子與變異子方法,來訪問數據成員的物件導向程式設計信條。就像Python提供函數式程式設計構造,但不嘗試要求參照透明性一樣,它提供對象系統,但不要求物件導向程式設計行為。
對象的方法,是附屬於這個對象的類的函數。對於正常的方法和函數,語法instance.method(arguments)
,是Class.method(instance, arguments)
的語法糖。Python的方法有顯式的self
形式參數,用來訪問實例數據;這借鑑自Modula-3,對立於隱式的self
或this
關鍵字,它們用在其他一些物件導向程式設計語言,比如C++、Java、Objective-C或Ruby之中[145]。在Python中,self
可以被看作是一個習慣用法,它可以被換為任何其它合法的參數名。[ad]
Python提供了super()
內建函數,在一個類的方法中呼叫此函數返回一個代理(proxy)對象,它將其方法呼叫委託給這個類的父類別或兄弟類[146],當一個子類的方法覆蓋了超類方法的時候,可通過呼叫super().method
,來呼叫與子類的self.method
方法同名超類別方法。[ae]
Python支援一些以__
開始和結束的特殊方法名,它們用於實現運算子多載,以及實現多種特殊功能[73]。在Python中,可以通過定義特殊方法來多載運算子,比如在一個類上定義__add__()
,將允許在這個類別的實例上使用+
算符。
在Python中,定義了一個或多個特殊方法__get__()
、__set__()
、__delete__()
的類,可以用作描述器(descriptor)[147]。建立一個描述器的實例,作為另一個類的一個類別成員,使得這個實例成為此另一個類的屬性(property)。使用與特性(attribute)訪問相同的語法,訪問一個實例對象中的這個成員屬性。[af]
Python允許通過使用@classmethod
和@staticmethod
修飾詞,來分別建立類別方法和靜態方法[55]。給類別方法的第一個實際參數,是對類對象的參照,而非對實例的self
參照。靜態方法沒有特定的第一個實際參數,實例或類對象,都不固定的傳遞給靜態方法。[ag]
Python的property
內建函數,將一個類中特殊定義的訪問一個特性的那些方法,包裝成的這個類的一個屬性[148]。[ah]
Python使用鴨子型別,並擁有有類型的對象,和無類型的變數名字。在編譯期不檢查類型約束,而寧願在一個對象上的操作出現可能的失敗,表現出這個給定對象不具有適合的類型。儘管是動態型別系統,Python卻是強型別的,禁止沒有明確定義的操作(比如加一個數到一個字串),而不是默默的去嘗試轉換使其有意義。Python支援廣泛的類型和類的內省。類型是type
的實例,可以被讀取和比較。
Python有着範圍廣泛的基本資料類型。同時具備常規的整數和浮點算術,它透明的支援任意精度算術、複數和十進制浮點數。Python支援種類繁多的字串操作。在Python中,字串是不可變的,所以在其他程式語言中可能就地改變字串的字串操作,比如字元替換,在Python中返回新的字串。
Python有一個非常有用特徵,就是搜集(或稱容器)類型的概念。一般的說,搜集是以一種易於參照或索引的方式,包含其他對象的對象。搜集有二種基本形式:序列和對映。Python對建立容器類型的對象有着語法上的支援。[ai]Python還提供了廣泛的搜集操縱能力,比如內建的包含元素檢查和通用迭代協定。
有次序的序列類型是列表(動態陣列)、元組和字串。所有序列類型都是位置索引的(從0
到长度−1
),並且除了字串,都可以包含任意類型的對象,在同一個序列中包括多種類型的對象。字串和元組是不可變的,使得它們成為字典的鍵的完美候選者。在另一方面,列表是可變的,元素可以被插入、刪除、修改、添加或就地排序。
在另一方面,對映是以「字典」形式實現的無次序的類型,它將一組不可變的鍵,對映到相應的元素上(非常像數學函數)。在字典中的鍵,必須是不可變的Python類型,比如整數或字串,因為在底層它們是通過雜湊函數實現的。字典還是語言內部的中心,因為它們居於所有Python對象和類的核心:在變數名字(字串)和這個名字所參照的值之間的對映,就儲存為字典,而這些字典可以通過對象的__dict__
特性直接訪問。
集合搜集類型,在版本2.4中被增加入語言核心。集合是無索引、無次序的搜集,它包含唯一性的不可變對象作為元素,並且實現了集合論運算,比如併集|
、交集&
、相對補集-
、對稱差^
,和子集測試<=
、真子集測試<
、超集測試>=
、真超集測試>
。有二種類型的集合:可變的set
和不可變的frozenset
。
Python允許程式者使用類,定義自己的類型[51],類是在物件導向程式設計中最經常使用的。類的新實例,是通過呼叫這個類的構造器而建立的,而類都是元類type
的實例,type
是type
元類自身的實例,這允許了元程式設計和反射。[aj]
在版本3.0之前,Python有兩種類:舊式的和新式的[150]。二種樣式的語法是一樣的,不同在於是否直接或間接的繼承自類object
,所有新式類都從object
繼承,並且是type
的實例。在Python 2系列2.2以上,二種類都可以使用[51]。在Python 3.0中淘汰了舊式類。
長期規劃是支援漸進類型[5],並且自從Python 3.5,語言的語法允許指定靜態型別,但在預設實現CPython中不檢查它們[141]。有叫做「mypy」的可選的靜態型別檢查器,支援編譯期型別檢查[151]。
類型 | 可變性 | 描述 | 語法例子 |
---|---|---|---|
bool
|
不可變 | 布林值,有表示值False 和True 的兩個對象。作為整數類型numbers.Integral 的子類型,它們在幾乎所有上下文中,表現得如同0 和1 ,除了在轉換成字串時轉換為"False" 和"True" 之外。
|
True False
|
int
|
不可變 | 整數,其大小在理論上無限制,實際上受限於主記憶體[152]。 | 42
|
float
|
不可變 | 雙精度浮點數,確切精度依賴於機器。一般實現為IEEE 754標準binary64浮點數,它有53個二進制有效數碼精度[153]。 | 1.414
|
complex
|
不可變 | 複數,即分別表示實部與虛部的兩個雙精度浮點數的有序對。 | 3+2.7j
|
range
|
不可變 | 數的序列,通常用在for 迴圈中指定迴圈次數[154]。
|
range(1, 10) range(10, -5, -2)
|
str
|
不可變 | 字串,即Unicode程式碼點序列。字串中的程式碼點都在範圍U+0000..U+10FFFF 之內。Python沒有char 類型,這些程式碼點都表示為長度為1 的字串對象。
|
'Wikipedia'
"Wikipedia"
"""Spanning
multiple lines"""
|
bytes
|
不可變 | 位元組序列,其專案是8位元位元組,用範圍0 <= x < 256 的整數表示。
|
b'Some ASCII' b"Some ASCII" bytes([0x53, 0x74, 0x72])
|
bytearray
|
可變 | bytearray(b'Some ASCII') bytearray(b"Some ASCII") bytearray([0x53, 0x74, 0x72])
| |
list
|
可變 | 列表,可以包含任意的Python對象。 | [4.0, 'string', True] []
|
tuple
|
不可變 | 元組,可以包含任意的Python對象。只有一個專案的元組,可以通過向表達式字尾一個逗號來形成。 | (4.0, 'string', True) ('single element',) ()
|
dict
|
可變 | 鍵-值對的關聯陣列(常稱為字典),即由任意索引集合來索引的對象的有限集合。不可接受為鍵的值,是列表或字典,或按值而非對象同一性比較的其他可變類型的值,其雜湊值不能保持恆定。 | {'key1': 1.0, 3: False} {}
|
set
|
可變 | 無序有限集合,包含唯一性的不可變的對象,它們不能用任何下標來索引。 | {4.0, 'string', True} set()
|
frozenset
|
不可變 | frozenset([4.0, 'string', True])
| |
types.EllipsisType
|
不可變 | 這個類型有一個單一對象作為值,它通過文字... 或內建名字Ellipsis 來訪問,它的真值為真。它用於NumPy多維陣列索引[155]。
|
... Ellipsis
|
types.NoneType
|
不可變 | 這個類型有叫做None 的一個單一對象Null 作為值[156],它被用來指示值的缺席,比如不返回任何東西的函數返回它,它的真值為假。
|
None
|
types.NotImplementedType
|
不可變 | 這個類型有一個單一對象NotImplemented 作為值。數值方法和細化比較方法,在它們仍未對提供的運算元實現這個運算之時,返回這個值。它不應該在布林值上下文中求值。
|
NotImplemented
|
除了各種資料類型,Python直譯器還內建了很多其他類型,包括可呼叫類型:用戶定義函數、實例方法、生成器函數、協程函數、非同步生成器函數、內建函數、內建方法、類、類別方法;模組,客製化類,類別實例,I/O對象(也叫做檔案對象),和暴露給用戶的一些內部類型:程式碼對象、框架對象、溯回對象、切片對象、靜態方法對象、類別方法對象。
Python的算術運算,使用平常的符號+
、-
、*
、/
和模除%
。它還有下取整除法算符//
、指數算符**
和矩陣乘法算符@
[118]。二元運算先將兩運算元轉為共同類型,加法、減法、乘法、下取整除法和指數運算的結果也採用此類型,比如5**3 == 125
而9**0.5 == 3.0
。這些算符就像在傳統數學中一樣運算,具有同樣的優先級規則,中綴算符+
、-
,還可以分別表示取原數和取相反數的一元算符。
被稱為「真除法」的/
的表現,隨着版本不同而有着顯著變化[157]。自Python 3.0以來,/
總是產生浮點數結果,包括兩個整數相除,比如5/2 == 2.5
;而在下取整除法//
中,兩個整數相除產生整數,比如7//3 == 2
而7.5//3 == 2.0
。
下取整除法//
的修約是朝向負無窮的。向下取整能增加一致性[158],例如這意味着等式(a + n)//n == a//n + 1
總是為真。模除%
所得出的餘數的符號同於除數,比如-4%3 == 2
而4%-3 == -2
。其它多數程式語言比如C99採用截尾取整規則,餘數的符號同於被除數。模除運算結果餘數的定義,確使等式a == (a//n)*n + a%n
對於a
和n
分別為正數或負數的情況都是有效的[159]。餘數可以為負數,顯著不同於在數學中的歐幾里得除法規則下,餘數總是非負數的情況。
Python提供了round()
內建函數,用於把一個浮點數修約成最近的整數[160],自Python 3.0以來,為了打破平局它採用了IEEE 754的約半成偶規則:round(1.5)
和round(2.5)
都產生2
。
Python允許由比較運算連結起來的布林表達式,表現得如在數學中常用的一樣。比如表達式a < b < c
,測試a < b and b < c
[120]。C語言將它解析為(a < b) < c
:即首先求值a < b
,其結果為0
或1
,接着把這個結果比較於c
[161]。
Python對所有整數運算,使用任意精度算術。在decimal
模組中的Decimal
類[162],提供十進制浮點數,具有用戶可按需要而更改的預設28個十進制有效數碼精度,並有多種修約方式[163]。在fractions
模組中的Fraction
類,提供任意精度的有理數[164]。第三方庫gmpy2[165],提供了到任意精度計算庫GMP/MPIR、MPFR和MPC的介面。
除了求絕對值函數abs()
列入內建函數之外,大多數數學函數,處於math
和cmath
模組內。前者用於實數運算,而後者用於複數運算。[ak]由於Python有着廣泛的數學庫,特別是第三方庫NumPy進一步擴充了原生能力,Python經常被用作科學手稿語言,來處理如數值數據處理和操縱等問題[166][167]。
Python擁有一個強大的標準庫[168]。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直譯器[169]。Python屬於動態語言,其官方實現將Python程式編譯成中間形式的位元組碼[170],並接着在它的虛擬機器上執行[171],相較於C/C++和java的等編譯語言而言執行速度較慢[172]。
async/await
關鍵字,和後來版本的一些選定特徵;它提供了實現Python標準庫模組功能子集的內建模組,和特定於微控制器的一些模組。CircuitPython是Adafruit開發的MicroPython分叉。wheel
形式的純Python包,並且已經移植了很多具有C語言擴充的包。libpython
庫,能完成嵌入所有模組的程式編譯、擴充模組及包編譯和獨立模態程式釋出。其他實現舉例:Jython,它是用Java實現的Python 2.7。IronPython,它是建造在DLR之上的Python 2.7和Python 3.4實現。Stackless Python,它是實現微線程的CPython 3.8分叉。Pyston,它是具有JIT等效能最佳化的CPython 3.8.12的分叉[186]。Pyjion,將Python程式碼編譯成本機CIL的CPython 3.10的JIT擴充[187]。Cinder,它是Meta孵化器釋出的具有包括JIT等很多最佳化的CPython 3.10分叉[188]。
很多並非整合式開發環境軟體的文字編輯器,也對Python有不同程度的支援,並且加上專門為Python設計的編輯器外掛程式也會有很高的可用性。
適用於Python的整合式開發環境(IDE)軟體,除了標準二進制釋出包所附的IDLE之外,還有許多其他選擇。其中有些軟體設計有語法着色、語法檢查、執行偵錯、自動補全、智能感知等便利功能。由於Python的跨平台出身,這些軟體往往也具備各種作業系統的版本或一定的移植性。
Python社群提供了大量的功能覆蓋眾多領域的第三方模組,其使用方式與標準庫類似。第三方模組可以使用Python/Cython或者C語言編寫。軟體工具SWIG和SIP,通過定義介面檔案或規定檔案的方式,可以將C/C++編寫的程式庫包裝為Python模組。Python直譯器本身也可以被整合到其它需要手稿語言的程式內。
Python包索引是公開的軟件套件線上倉庫。pip是官網推薦的以安全方式安裝Python應用及其依賴軟件套件的最流行工具[189]。要安裝在整個作業系統範圍內共用的Python包,現在需要通過作業系統的軟件套件管理系統。要將特定於應用的依賴包隔離於共用的Python安裝,可以使用標準庫的venv[190]或第三方工具virtualenv[191]建立虛擬環境;第三方工具pipenv,能自動為用戶專案建立和管理虛擬環境,並在安裝/卸裝軟件套件的時候,向此專案的Pipfile檔案增加/移除這個軟件套件[192]。
Python定義了WSGI標準應用介面,來協調HTTP伺服器與基於Python的Web程式之間的溝通。比如,通過mod_wsgi模組,Apache可以運行用Python編寫的Web程式。Zope是著名的用Python編寫的開源的Web應用伺服器。Tornado是用Python語言寫成的非阻塞式web伺服器,也是輕量級的Web框架。
Python對於各種網絡協定的支援很完善,因此適用於編寫伺服器軟體、網絡爬蟲等Web開發。用Python編寫的一些Web框架,有助於輕鬆地開發和管理複雜的Web程式。著名的第三方Web框架和函式庫:
asyncio
事件迴圈的快速的、直截了當的替代者[195],它用Cython實現並在底層使用了libuv。asyncio
的HTTP客戶端和伺服器二者[196]。Python本身包含了Tkinter庫,它是Python的業界標準GUI並被整合進入了IDLE。Tkinter基於了Tcl命令工具,能夠支援簡單的GUI開發。但是為了讓所開發的軟體執行速度更快,並與用戶的桌面環境更契合,人們一般會選擇採用第三方GUI庫或框架。著名的第三方GUI庫:
重要的數據科學用第三方軟體庫有:
基礎性的機器學習軟體庫及框架有:
在很多作業系統裏,Python是標準的系統元件,它被列入Linux標準規範之中[253]。大多數Linux發行版和macOS都整合了Python,可以在終端模擬器或虛擬控制台下直接執行Python。第三方工具pipx,可以將Python應用安裝於隔離的環境中並在其中執行它[254]。
雖然Python可被粗略地分類為手稿語言,Python的支持者較喜歡稱它為一種高階動態語言,常像「膠水」一樣被用來連接軟體組件,已經顯著的區別於Unix shell、Windows PowerShell這樣的語言。基於Python的xonsh,是跨平台的、青睞Unix的shell語言和命令列介面[255]。
一些Linux發行版,使用Python語言編寫安裝器,比如Ubuntu的Ubiquity和Fedora的Anaconda;或使用它編寫軟件包管理系統,比如Gentoo的Portage。如下著名應用使用Python編寫或將它作為嵌入式指令碼:
經由Python開發了眾多的人工智能模型和作為其支撐的軟體庫:
自從2003年,Python始終排行於TIOBE程式社區索引前十最流行程式語言,在2021年10月它首次達到了第一名最流行語言(居於C和Java之前)[268],並被選為2007年、2010年、2018年、2020年和2021年的年度程式語言[268]。它有如下著名的社群:
Python的設計和哲學已經影響了很多其他程式語言:
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.