python语法详解大全_笔记:Python 语法要点汇总
Python 是一門解釋型語言,無需編譯和鏈接
Python 解釋器
交互模式
腳本模式
源碼編碼
默認情況下,Python 源文件是 UTF-8 編碼
指定源文件的字符編碼
# -*- coding:utf-8 -*-注釋,#注釋 及"""注釋"""
數(shù)據(jù)結(jié)構
標準數(shù)據(jù)類型
ython3 中有六個標準的數(shù)據(jù)類型:Number(數(shù)字)
String(字符串)
List(列表)
Tuple(元組)
Set(集合)
Dictionary(字典)
Python3 的六個標準數(shù)據(jù)類型中:不可變數(shù)據(jù)(3 個):Number(數(shù)字)、String(字符串)、Tuple(元組);
可變數(shù)據(jù)(3 個):List(列表)、Dictionary(字典)、Set(集合)。
數(shù)字(Number)
Python3 支持 int、float、bool、complex(復數(shù))
整數(shù)類型是 int,帶有小數(shù)部分的數(shù)字類型是 float
使用 / 運算符返回浮點數(shù),使用 //運算符返回整數(shù)
變量在使用前必須 “定義”(賦值),否則會出錯
浮點數(shù)有完整的支持;整數(shù)和浮點數(shù)的混合計算中,整數(shù)會被轉(zhuǎn)換為浮點數(shù)
交互模式中,最近一個表達式的值賦給變量_
數(shù)字型變量對于用戶是只讀的,再次賦值只會創(chuàng)建獨立的同名變量
字符串(String)
用單引號 ('...') 或雙引號 ("...") 標識字符串,效果相同
\可以用來轉(zhuǎn)義引號
在交互式解釋器中,輸出的字符串會用引號引起來,特殊字符會用反斜杠轉(zhuǎn)義
在第一個引號前面加上一個r ,可獲取原始字符串
字符串文本能夠分成多行,使用三引號:"""..."""或者'''...''',
行尾換行符會被自動包含到字符串中,可以在行尾加上\來避免這個行為
字符串可以由+操作符連接(粘到一起),可以由*表示重復
相鄰的兩個字符串文本自動連接在一起,只用于兩個字符串文本,不能用于字符串表達式
Python沒有單獨的字符類型;一個字符就是一個簡單的長度為1的字符串
字符串可以被截取(檢索),索引值以 0 為開始值,-1 為從末尾的開始位置
注意 -0 實際上就是 0,所以它不會導致從右邊開始計算
字符串支持切片
索引用于獲得單個字符,切片讓你獲得一個子字符串
注意,包含起始的字符,不包含末尾的字符。這使得s[:i]?+?s[i:]永遠等于s
切片的索引有非常有用的默認值;省略的第一個索引默認為零,省略的第二個索引默認為切片的字符串的大小
切片的工作方式:切片時的索引是在兩個字符之間
左邊第一個字符的索引為 0,而長度為n的字符串其最后一個字符的右界索引為n
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6-6 -5 -4 -3 -2 -1對于非負索引,如果上下都在邊界內(nèi),切片長度就是兩個索引之差
試圖使用太大的索引會導致錯誤
一個過大的索引值(即下標值大于字符串實際長度)將被字符串實際長度所代替,
當上邊界比下邊界大時(即切片左值大于右值)就返回空字符串
Python字符串不可以被更改,它們是不可變的;賦值給字符串索引的位置會導致錯誤
內(nèi)置函數(shù)len()返回字符串長度
特殊字符例如\n在單引號('...')和雙引號("...")中具有相同的含義。
兩者唯一的區(qū)別是在單引號中,你不需要轉(zhuǎn)義"(但你必須轉(zhuǎn)義\')
列表(List)
列表時括號之間的一列逗號分隔的值
列表的元素不必是同一類型
列表可以被索引和切片,所有的切片操作都會返回一個包含請求的元素的新列表
列表支持連接操作
列表是可變的,允許修改元素
可以對切片賦值,此操作可以改變列表的尺寸,或清空它
內(nèi)置函數(shù)len()同樣適用于列表
允許嵌套列表(創(chuàng)建一個包含其它列表的列表)
在列表的末尾添加新的元素,append(x)
在指定位置插入一個元素。第一個參數(shù)是準備插入到其前面的那個元素的索引,list.insert(i,x)
刪除列表中值為x的第一個元素,list.remove(x);如果沒有這樣的元素,就會返回一個錯誤
從列表的指定位置刪除元素,并將其返回,list.pop([i]);如果沒有指定索引,a.pop()返回最后一個元素
從列表中刪除所有元素,list.clear()
返回列表中第一個值為x的元素的索引,list.index(x);如果沒有匹配的元素就會返回一個錯誤
返回x在列表中出現(xiàn)的次數(shù),list.count(x);
對列表中的元素就地進行排序,list.sort()
就地倒排列表中的元素,list.reverse()
返回列表的一個淺拷貝,list.copy();等同于a[:]
將一個給定列表中的所有元素都添加到另一個列表中,list.extend(L)
把列表當作堆棧使用
堆棧作為特定的數(shù)據(jù)結(jié)構,最先進入的元素最后一個被釋放(后進先出)
用append()方法可以把一個元素添加到堆棧頂。用不指定索引的pop()方法可以把一個元素從堆棧頂釋放出來
把列表當作隊列使用
隊列作為特定的數(shù)據(jù)結(jié)構,最先進入的元素最先釋放(先進先出)
不過,列表這樣用效率不高。相對來說從列表末尾添加和彈出很快;在頭部插入和彈出很慢(因為,為了一個元素,要移動整個列表中的所有元素)
要實現(xiàn)隊列,使用collections.deque,它為在首尾兩端快速插入和刪除而設計
列表推導式
列表推導式由包含一個表達式的括號組成,表達式后面跟隨一個for子句,之后可以有零或多個for或if子句。結(jié)果是一個列表,由表達式依據(jù)其后面的for和if子句上下文計算而來的結(jié)果構成
列表推導式為從序列中創(chuàng)建列表提供了一個簡單的方法
squares?x?()squares.append(x)注意這個 for 循環(huán)中的被創(chuàng)建(或被重寫)的名為x的變量在循環(huán)完畢后依然存在
squares?xx?()列表推導式可使用復雜的表達式和嵌套函數(shù)
嵌套的列表推導式
列表解析中的第一個表達式可以是任何表達式,包括列表解析
del語句
從列表中按給定的索引而不是值來刪除一個子項:del語句
不同于有返回值的pop()方法,語句del可以從列表中刪除切片或清空整個列表
del也可以刪除整個變量
元組
一個元組由數(shù)個逗號分隔的值組成
元組在輸出時總是有括號的,以便于正確表達嵌套結(jié)構。
在輸入時可以有或沒有括號,不過經(jīng)常括號都是必須的(如果元組是一個更大的表達式的一部分)
不能給元組的一個獨立的元素賦值(盡管你可以通過聯(lián)接和切割來模擬)。
可以創(chuàng)建包含可變對象的元組,例如列表
元組有很多用途。例如 (x, y) 坐標對,數(shù)據(jù)庫中的員工記錄等等。
元組就像字符串,不可變的。
通常包含不同種類的元素并通過分拆(參閱本節(jié)后面的內(nèi)容) 或索引訪問(如果是namedtuples,甚至可以通過屬性)
一對空的括號可以創(chuàng)建空元組;empty=()
要創(chuàng)建一個單元素元組可以在值后面跟一個逗號:singleton='hello',
(在括號中放入一個單值不夠明確)
集合
集合是一個無序不重復元素的集
基本功能包括關系測試和消除重復元素
大括號或set()函數(shù)可以用來創(chuàng)建集合
創(chuàng)建空集合,你必須使用set()而不是{},后者用于創(chuàng)建空字典
集合推導式語法,a={xforxin'abracadabra'ifxnotin'abc'}
字典
字典在某些語言中可能稱為 聯(lián)合內(nèi)存 ( associative memories )或 聯(lián)合數(shù)組 ( associative arrays )
字典以關鍵字為索引,關鍵字可以是任意不可變類型,通常用字符串或數(shù)值
理解字典的最佳方式是把它看做無序的鍵:值對(key:value 對)集合,鍵必須是互不相同的(在同一個字典之內(nèi))
一對大括號創(chuàng)建一個空的字典:{}
初始化列表時,在大括號內(nèi)放置一組逗號分隔的鍵:值對,這也是字典輸出的方式
字典的主要操作是依據(jù)鍵來存儲和析取值
可以用del來刪除鍵:值對(key:value)
用一個已經(jīng)存在的關鍵字存儲值,以前為該關鍵字分配的值就會被遺忘
試圖從一個不存在的鍵中取值會導致錯誤。
對一個字典執(zhí)行l(wèi)ist(d.keys())將返回一個字典中所有關鍵字組成的無序列表
如果你想要排序,只需使用sorted(d.keys())
使用in關鍵字(指Python語法)可以檢查字典中是否存在某個關鍵字(指字典)
dict()構造函數(shù)可以直接從 key-value 對中創(chuàng)建字典dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
字典推導式可以從任意的鍵值表達式中創(chuàng)建字
如果關鍵字都是簡單的字符串,有時通過關鍵字參數(shù)指定 key-value 對更為方便
dict(sape=4139, guido=4127, jack=4098)
循環(huán)技巧
在字典中循環(huán)時,關鍵字和對應的值可以使用items()方法同時解讀出來:
knights = {'gallahad': 'the pure', 'robin': 'the brave'}for k, v in knights.items():? ??print(k,v)
在序列中循環(huán)時,索引位置和對應值可以使用enumerate()函數(shù)同時得到
for i, v in enumerate(['tic', 'tac', 'toe']):? ??print(i,v)
同時循環(huán)兩個或更多的序列,可以使用zip()整體打包:
questions = ['name', 'quest', 'favorite color']answers = ['lancelot', 'the holy grail', 'blue']for q, a in zip(questions, answers):? ??print('What is your{0}? ?It is{1}.'.format(q,a))
需要逆向循環(huán)序列的話,先正向定位序列,然后調(diào)用reversed()函數(shù):
for i in reversed(range(1, 10, 2)):? ??print(i)
要按排序后的順序循環(huán)序列的話,使用sorted()函數(shù),它不改動原序列,而是生成一個新的已排序的序列:
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']for f in sorted(set(basket)):? ??print(f)
若要在循環(huán)內(nèi)部修改正在遍歷的序列(例如復制某些元素),建議您首先制作副本。在序列上循環(huán)不會隱式地創(chuàng)建副本。切片表示法使這尤其方便:
words = ['cat', 'window', 'defenestrate']for w in words[:]: # Loop over a slice copy of the entire list.if len(w) > 6:words.insert(0, w)
深入條件控制
while和if語句中使用的條件不僅可以使用比較,而且可以包含任意的操作
比較操作符in和not?in審核值是否在一個區(qū)間之內(nèi)
操作符is和is?not比較兩個對象是否相同
所有的比較操作符具有相同的優(yōu)先級,低于所有的數(shù)值操作
比較操作可以傳遞。例如a?
比較操作可以通過邏輯操作符and和or組合,比較的結(jié)果可以用not來取反義
邏輯操作符and和or也稱作短路操作符,它們的參數(shù)從左向右解析,一旦結(jié)果可以確定就停止
如果A和C為真而B為假,A?and?B?and?C不會解析C
作用于一個普通的非邏輯值時,短路操作符的返回值通常是最后一個變量
可以把比較或其它邏輯表達式的返回值賦給一個變量
需要注意的是 Python 與 C 不同,在表達式內(nèi)部不能賦值
比較序列和其它類型
序列對象可以與相同類型的其它對象比較
比較操作按字典序進行:首先比較前兩個元素,如果不同,就決定了比較的結(jié)果;如果相同,就比較后兩個元素,依此類推,直到所有序列都完成比較
如果兩個元素本身就是同樣類 型的序列,就遞歸字典序比較。如果兩個序列的所有子項都相等,就認為序列相等
如果一個序列是另一個序列的初始子序列,較短的一個序列就小于另一個
字符串的字典序按照單字符的 ASCII 順序
需要注意的是如果通過比較的對象只要具有合適的比較方法就是合法的
控制流程
if?語句
if…elif…elif… 序列用于替代其它語言中的switch或case語句
Python 的for語句依據(jù)任意序列(鏈表或字符串)中的子項,按它們在序列中的順序來進行迭代
(通常的循環(huán)可能會依據(jù)一個等差數(shù)值步進過程(如 Pascal),或由用戶來定義迭代步驟和中止條件)
在迭代過程中修改迭代序列不安全(只有在使用鏈表這樣的可變序列時才會有這樣的情況)
如果你需要一個數(shù)值序列,內(nèi)置函數(shù)range()會很方便,它生成一個等差級數(shù)鏈表:
for i in range(5):? ??print(i)
range(10)生成了一個包含 10 個值的鏈表,它用鏈表的索引值填充了這個長度為 10 的列表,所生成的鏈表中不包括范圍中的結(jié)束值。也可以讓range()操作從另一個數(shù)值開始,或者可以指定一個不同的步進值(甚至是負數(shù),有時這也被稱為 “步長”):
range(5, 10)
5 through 9range(0, 10, 3)
0, 3, 6, 9range(-10, -100, -30)
-10, -40, -70
需要迭代鏈表索引的話,如下所示結(jié)合使 用range()和len()
a = ['Mary', 'had', 'a', 'little', 'lamb']for i in range(len(a)):print(i,a[i])
輸出
0 Mary1 had2 a3 little4 lamb不過,這種場合可以方便的使用enumerate()
在不同方面?range()?函數(shù)返回的對象表現(xiàn)為它是一個列表,但事實上它并不是。當你迭代它時,它是一個能夠像期望的序列返回連續(xù)項的對象;但為了節(jié)省空間,它并不真正構造列表。
我們稱此類對象是?可迭代的,即適合作為那些期望從某些東西中獲得連續(xù)項直到結(jié)束的函數(shù)或結(jié)構的一個目標(參數(shù))。我們已經(jīng)見過的?for?語句就是這樣一個迭代器。list()?函數(shù)是另外一個(?迭代器?),它從可迭代(對象)中創(chuàng)建列表
break語句和 C 中的類似,用于跳出最近的一級for或while循環(huán)
循環(huán)可以有一個else子句;它在循環(huán)迭代完整個列表(對于for)或執(zhí)行條件為 false (對于while)時執(zhí)行,但循環(huán)被break中止的情況下不會執(zhí)行
與循環(huán)一起使用時,else子句與try語句的else子句比與if語句的具有更多的共同點:try語句的else子句在未出現(xiàn)異常時運行,循環(huán)的else子句在未出現(xiàn)break時運行。更多關于try語句和異常的內(nèi)容,請參見異常處理。
continue語句是從 C 中借鑒來的,它表示循環(huán)繼續(xù)執(zhí)行下一次迭代,(結(jié)束本次循環(huán)執(zhí)行語句,開始下一次循環(huán))
pass語句什么也不做。它用于那些語法上必須要有什么語句,但程序什么也不做的場合
這通常用于創(chuàng)建最小結(jié)構的類:
class MyEmptyClass:pass
另一方面,pass可以在創(chuàng)建新代碼時用來做函數(shù)或控制體的占位符。可以讓你在更抽象的級別上思考。pass可以默默的被忽視:
def initlog(*args):? ??pass# Remember to implement this!
定義函數(shù)
關鍵字def引入了一個函數(shù)定義。在其后必須跟有函數(shù)名和包括形式參數(shù)的圓括號。函數(shù)體語句從下一行開始,必須是縮進的
函數(shù)體的第一行語句可以是可選的字符串文本,這個字符串是函數(shù)的文檔字符串,或者稱為docstring。
在你的代碼中包含 docstrings 是一個好的實踐
函數(shù)調(diào)用會為函數(shù)局部變量生成一個新的符號表,所有函數(shù)中的變量賦值都是將值存儲在局部符號表
變量引用首先在局部符號表中查找,然后是包含函數(shù)的局部符號表,然后是全局符號表,最后是內(nèi)置名字表
全局變量不能在函數(shù)中直接賦值(除非用global語句命名),盡管他們可以被引用
函數(shù)引用的實際參數(shù)在函數(shù)調(diào)用時引入局部符號表,因此,實參總是傳值調(diào)用(這里的值總是一個對象 引用 ,而不是該對象的值)。[1]一個函數(shù)被另一個函數(shù)調(diào)用時,一個新的局部符號表在調(diào)用過程中被創(chuàng)建
一個函數(shù)定義會在當前符號表內(nèi)引入函數(shù)名。函數(shù)名指代的值(即函數(shù)體)有一個被 Python 解釋器認定為用戶自定義函數(shù)的類型。 這個值可以賦予其他的名字(即變量名),然后它也可以被當做函數(shù)使用。這可以作為通用的重命名機制
return語句從函數(shù)中返回一個值,不帶表達式的return返回None
過程結(jié)束后也會返回None
語句result.append(b)稱為鏈表對象result的一個方法。方法是一個“屬于”某個對象的函數(shù),它被命名為obj.methodename,這里的obj是某個對象(可能是一個表達式),methodename是某個在該對象類型定義中的方法的命名
不同的類型定義不同的方法。不同類型可能有同樣名字的方法,但不會混淆。(當你定義自己的對象類型和方法時,可能會出現(xiàn)這種情況,class的定義方法詳見類)
深入 Python 函數(shù)定義
在 Python 中,可以定義包含若干參數(shù)的函數(shù)
默認參數(shù)值
最常用的一種形式是為一個或多個參數(shù)指定默認值
這個函數(shù)可以通過幾種不同的方式調(diào)用:只給出必要的參數(shù):
ask_ok('Do?you?really?want?to?quit?')
給出一個可選的參數(shù):
ask_ok('OK?to?overwrite?the?file?',?2)
或者給出所有的參數(shù):
ask_ok('OK?to?overwrite?the?file?',?2,?'Come?on,?only?yes?or?no!')
這個例子還介紹了?in?關鍵字。它測定序列中是否包含某個確定的值。
默認值在函數(shù)定義作用域被解析重要警告:默認值只被賦值一次。這使得當默認值是可變對象時會有所不同,比如列表、字典或者大多數(shù)類的實例關鍵字參數(shù)函數(shù)可以通過關鍵字參數(shù)的形式來調(diào)用,形如keyword?=?value在函數(shù)調(diào)用中,關鍵字的參數(shù)必須跟隨在位置參數(shù)的后面。傳遞的所有關鍵字參數(shù)必須與函數(shù)接受的某個參數(shù)相匹配 (例如actor不是parrot函數(shù)的有效參數(shù)),它們的順序并不重要
任何參數(shù)都不可以多次賦值
引入一個形如**name的參數(shù)時,它接收一個字典(參見Mapping Types — dict),該字典包含了所有未出現(xiàn)在形式參數(shù)列表中的關鍵字參數(shù)
可變參數(shù)列表
一個最不常用的選擇是可以讓函數(shù)調(diào)用可變個數(shù)的參數(shù)。這些參數(shù)被包裝進一個元組
通常,這些可變參數(shù)是參數(shù)列表中的最后一個,因為它們將把所有的剩余輸入?yún)?shù)傳遞給函數(shù)。任何出現(xiàn)在*args后的參數(shù)是關鍵字參數(shù),這意味著,他們只能被用作關鍵字,而不是位置參數(shù):
參數(shù)列表的分拆
當要傳遞的參數(shù)已經(jīng)是一個列表,但要調(diào)用的函數(shù)卻接受分開一個個的參數(shù)值,要把已有的列表拆開來,可以在調(diào)用函數(shù)時加一個*操作符來自動把參數(shù)列表拆開
同樣的方式,可以使用**操作符分拆關鍵字參數(shù)為字典
Lambda 形式
通過lambda關鍵字,可以創(chuàng)建短小的匿名函數(shù)
這里有一個函數(shù)返回它的兩個參數(shù)的和:lambda?a,?b:?a+b。 Lambda 形式可以用于任何需要的函數(shù)對象。出于語法限制,它們只能有一個單獨的表達式。語義上講,它們只是普通函數(shù)定義中的一個語法技巧。類似于嵌套函數(shù)定義,lambda 形式可以從外部作用域引用變量
文檔字符串
第一行應該是關于對象用途的簡介
如果文檔字符串有多行,第二行應該空出來,與接下來的詳細描述明確分隔
接下來的文檔應該有一或多段描述對象的調(diào)用約定、邊界效應等
Python 的解釋器不會從多行的文檔字符串中去除縮進,所以必要的時候應當自己清除縮進
第一行之后的第一個非空行決定了整個文檔的縮進格式
每一行都不應該有縮進,如果有縮進的話,所有的留白都應該清除掉
函數(shù)注解
函數(shù)注解是關于用戶自定義的函數(shù)的完全可選的、隨意的元數(shù)據(jù)信息
注解是以字典形式存儲在函數(shù)的__annotations__屬性中,對函數(shù)的其它部分沒有任何影響。參數(shù)注解(Parameter annotations)是定義在參數(shù)名稱的冒號后面,緊隨著一個用來表示注解的值得表達式。返回注釋(Return annotations)是定義在一個->后面,緊隨著一個表達式,在冒號與->之間
編碼風格
使用 4 空格縮進,而非 TAB
在小縮進(可以嵌套更深)和大縮進(更易讀)之間,4空格是一個很好的折中。TAB 引發(fā)了一些混亂,最好棄用
折行以確保其不會超過 79 個字符
這有助于小顯示器用戶閱讀,也可以讓大顯示器能并排顯示幾個代碼文件
使用空行分隔函數(shù)和類,以及函數(shù)中的大塊代碼
可能的話,注釋獨占一行
使用文檔字符串
把空格放到操作符兩邊,以及逗號后面,但是括號里側(cè)不加空格:a=f(1,2)+g(3,4)
統(tǒng)一函數(shù)和類命名
推薦類名用駝峰命名, 函數(shù)和方法名用小寫_和_下劃線??偸怯胹elf作為方法的第一個參數(shù)(關于類和方法的知識詳見初識類)
不要使用花哨的編碼,如果你的代碼的目的是要在國際化環(huán)境。Python 的默認情況下,UTF-8,甚至普通的 ASCII 總是工作的最好
同樣,也不要使用非 ASCII 字符的標識符,除非是不同語種的會閱讀或者維護代碼
模塊
Python 提供了一個方法可以從文件中獲取定義,在腳本或者解釋器的一個交互式實例中使用。這樣的文件被稱為模塊;
模塊中的定義可以導入到另一個模塊或主模塊中(在腳本執(zhí)行時可以調(diào)用的變量集位于最高級,并且處于計算器模式)
模塊是包括 Python 定義和聲明的文件,文件名就是模塊名加上.py后綴
模塊的模塊名(做為一個字符串)可以由全局變量__name__得到
如果打算頻繁使用一個函數(shù),你可以將它賦予一個本地變量
fib =fibo.fib
print(fib(500))
深入模塊
除了包含函數(shù)定義外,模塊也可以包含可執(zhí)行語句,
這些語句一般用來初始化模塊。他們僅在第一次被導入的地方執(zhí)行一次
每個模塊都有自己私有的符號表,被模塊內(nèi)所有的函數(shù)定義作為全局符號表使用
模塊的作者可以在模塊內(nèi)部使用全局變量,而無需擔心它與某個用戶的全局變量意外沖突
可以使用引用模塊函數(shù)的表示法訪問模塊的全局變量,modname.itemname
模塊可以導入其他的模塊
一個(好的)習慣是將所有的import語句放在模塊的開始
被導入的模塊名會放入當前模塊的全局符號表中
import語句的一個變體直接從被導入的模塊中導入命名到本模塊的語義表中
fromfibo importfib,fib2
fib(500)這樣不會從局域語義表中導入模塊名
有種方式可以導入模塊中的所有定義,可以導入所有除了以下劃線(_)開頭的命名
fromfibo import*需要注意的是在實踐中往往不鼓勵從一個模塊或包中使用*導入所有,因為這樣會讓代碼變得很難讀
出于性能考慮,每個模塊在每個解釋器會話中只導入一遍。因此,如果你修改了你的模塊,需要重啟解釋器;或者,如果你就是想交互式的測試這么一個模塊,可以用imp.reload()重新加載,例如importimp;imp.reload(modulename)。
作為腳本來執(zhí)行模塊
使用以下方式運行 Python 模塊時,模塊中的代碼便會被執(zhí)行
python fibo.py 模塊中的代碼會被執(zhí)行,就像導入它一樣,不過此時__name__被設置為"__main__"。這相當于,如果你在模塊后加入如下代碼
if__name__ =="__main__":importsys
fib(int(sys.argv[1]))
可以讓此文件像作為模塊導入時一樣作為腳本執(zhí)行。此代碼只有在模塊作為 “main” 文件執(zhí)行時才被調(diào)用
通常用來為模塊提供一個便于測試的用戶接口(將模塊作為腳本執(zhí)行測試需求)
模塊的搜索路徑
導入一個叫spam的模塊時,解釋器先在當前目錄中搜索名為spam.py的文件。如果沒有找到的話,接著會到sys.path變量中給出的目錄列表中查找。sys.path變量的初始值來自如下:
輸入腳本的目錄(當前目錄)。
環(huán)境變量PYTHONPATH表示的目錄列表中搜索
(這和 shell 變量PATH具有一樣的語法,即一系列目錄名的列表)。
Python 默認安裝路徑中搜索
在支持符號連接的文件系統(tǒng)中,輸入的腳本所在的目錄是符號連接指向的目錄。 換句話說也就是包含符號鏈接的目錄不會被加到目錄搜索路徑
解釋器由sys.path變量指定的路徑目錄搜索模塊,該變量初始化時默認包含了輸入腳本(或者當前目錄),PYTHONPATH和安裝目錄
“編譯的” Python 文件
為了加快加載模塊的速度,Python 會在__pycache__目錄下以module.version.pyc名字緩存每個模塊編譯后的版本,這里的版本編制了編譯后文件的格式。它通常會包含 Python 的版本號
為了減少一個編譯模塊的大小,你可以在 Python 命令行中使用-O或者-OO。-O參數(shù)刪除了斷言語句,-OO參數(shù)刪除了斷言語句和 __doc__ 字符串。
因為某些程序依賴于這些變量的可用性,你應該只在確定無誤的場合使用這一選項。“優(yōu)化的” 模塊有一個 .pyo 后綴而不是 .pyc 后綴。未來的版本可能會改變優(yōu)化的效果。
來自.pyc文件或.pyo文件中的程序不會比來自.py文件的運行更快;.pyc或.pyo文件只是在它們加載的時候更快一些。
compileall模塊可以為指定目錄中的所有模塊創(chuàng)建.pyc文件(或者使用-O參數(shù)創(chuàng)建.pyo文件)。
在 PEP 3147 中有很多關這一部分內(nèi)容的細節(jié),并且包含了一個決策流程。
標準模塊
sys,這個模塊內(nèi)置于所有的 Python 解釋器
變量sys.path是解釋器模塊搜索路徑的字符串列表
內(nèi)置函數(shù)dir()用于按模塊名搜索模塊定義,它返回一個字符串類型的存儲列表
無參數(shù)調(diào)用時,dir()函數(shù)返回當前定義的命名
dir()不會列出內(nèi)置函數(shù)和變量名。如果你想列出這些內(nèi)容,它們在標準模塊builtins中定義
包
包通常是使用用“圓點模塊名”的結(jié)構化模塊命名空間
當導入這個包時,Python 通過sys.path搜索路徑查找包含這個包的子目錄
用戶可以每次只導入包里的特定模塊
importsound.effects.echo這樣就導入了sound.effects.echo子模塊,必需通過完整的名稱來引用
sound.effects.echo.echofilter(input,output,delay=0.7,atten=4)
導入包時有一個可以選擇的方式
fromsound.effects importecho這樣就加載了echo子模塊,并且使得它在沒有包前綴的情況下也可以使用,所以它可以如下方式調(diào)用:
echo.echofilter(input,output,delay=0.7,atten=4)
還有另一種變體用于直接導入函數(shù)或變量
fromsound.effects.echo importechofilter這樣就又一次加載了echo子模塊,但這樣就可以直接調(diào)用它的echofilter()函數(shù):
echofilter(input,output,delay=0.7,atten=4)
需要注意的是使用frompackageimportitem方式導入包時,這個子項(item)既可以是包中的一個子模塊(或一個子包),也可以是包中定義的其它命名,像函數(shù)、類或變量
import語句首先核對是否包中有這個子項,如果沒有,它假定這是一個模塊,并嘗試加載它。如果沒有找到它,會引發(fā)一個ImportError異常
相反,使用類似importitem.subitem.subsubitem這樣的語法時,這些子項必須是包,最后的子項可以是包或模塊,但不能是前面子項中定義的類、函數(shù)或變量
從 * 導入包
給提供一個明確的包索引,
import語句按如下條件進行轉(zhuǎn)換:執(zhí)行frompackageimport*時,如果包中的__init__.py代碼定義了一個名為__all__的列表,就會按照列表中給出的模塊名進行導入
__all__ = ["echo", "surround", "reverse"]這意味著fromsound.effectsimport*語句會從sound包中導入以上三個已命名的子模塊
如果沒有定義__all__,fromsound.effectsimport*語句不會從sound.effects包中導入所有的子模塊。無論包中定義多少命名,只能確定的是導入了sound.effects包(可能會運行__init__.py中的初始化代碼)以及包中定義的所有命名會隨之導入。
盡管某些模塊設計為使用import*時它只導出符合某種規(guī)范/模式的命名,仍然不建議在生產(chǎn)代碼中使用這種寫法
記住,fromPackageimportspecific_submodule沒有錯誤!事實上,除非導入的模塊需要使用其它包中的同名子模塊,否則這是推薦的寫法
包內(nèi)引用
果包中使用了子包結(jié)構(就像示例中的sound包),可以按絕對位置從相鄰的包中引入子模塊。例如,如果sound.filters.vocoder包需要使用sound.effects包中的echo模塊,它可以fromsound.Effectsimportecho
可以用這樣的形式frommoduleimportname來寫顯式的相對位置導入。那些顯式相對導入用點號標明關聯(lián)導入當前和上級包
需要注意的是顯式或隱式相對位置導入都基于當前模塊的命名。因為主模塊的名字總是"__main__",Python 應用程序的主模塊應該總是用絕對導入
多重目錄中的包
包支持一個更為特殊的特性,__path__
在包的__init__.py文件代碼執(zhí)行之前,該變量初始化一個目錄名列表。該變量可以修改,它作用于包中的子包和模塊的搜索功能
事實上函數(shù)定義既是“聲明”又是“可執(zhí)行體”;執(zhí)行體由函數(shù)在模塊全局語義表中的命名導入
輸入和輸出
格式化輸出
函數(shù)str()用于將值轉(zhuǎn)化為適于人閱讀的形式,而repr()轉(zhuǎn)化為供解釋器讀取的形式
str.rjust()方法,把字符串輸出到一列,并通過向左側(cè)填充空格來使其右對齊
str.zfill()它用于向數(shù)值的字符串表達左側(cè)填充 0,該函數(shù)可以正確理解正負號
print('We are the{}who say "{}!"'.format('knights', 'Ni'))
大括號和其中的字符會被替換成傳入str.format()的參數(shù)
大括號中的數(shù)值指明使用傳入str.format()方法的對象中的哪一個
如果在str.format()調(diào)用時使用關鍵字參數(shù),可以通過參數(shù)名來引用值
print('This{food}is{adjective}.'.format(food='spam', adjective='absolutely horrible'))
'!a'(應用ascii()),'!s'(應用str())和'!r'(應用repr())可以在格式化之前轉(zhuǎn)換值
importmath
print('The value of PI is approximately {}.'.format(math.pi))print('The value of PI is approximately {!r}.'.format(math.pi))輸出
The value of PI is approximately 3.141592653589793.
The value of PI is approximately 3.141592653589793.
在字段后的':'后面加一個整數(shù)會限定該字段的最小寬度,這在美化表格時很有用
table ={'Sjoerd':4127,'Jack':4098,'Dcab':7678}forname,phone intable.items():print('{0:10} ==> {1:10d}'.format(name,phone))輸出
Sjoerd ==> 4127
Jack ==> 4098
Dcab ==> 7678
舊式的字符串格式化
操作符%也可以用于字符串格式化
print('The value of PI is approximately%5.3f.' % math.pi)
文件讀寫
函數(shù)open()返回文件對象,通常的用法需要兩個參數(shù):open(filename,mode)
f = open('workfile', 'w')
錯誤和異常
語法錯誤
語法錯誤,也被稱作解析錯誤
異常
運行期檢測到的錯誤稱為異常,并且程序不會無條件的崩潰
異常也有不同的類型
打印錯誤信息時,異常的類型作為異常的內(nèi)置名顯示
內(nèi)置的異常列出了內(nèi)置異常和它們的含義
異常處理
通過編程處理選擇的異常是可行的
while True:try:x =int(input("Please enter a number: "))breakexceptValueError:print("Oops! That was no valid number. Try again...")
try語句按如下方式工作。首先,執(zhí)行try子句 (在try和except關鍵字之間的部分)。
如果沒有異常發(fā)生,except子句 在try語句執(zhí)行完畢后就被忽略了。
如果在 try 子句執(zhí)行過程中發(fā)生了異常,那么該子句其余的部分就會被忽略。
如果異常匹配于except關鍵字后面指定的異常類型,就執(zhí)行對應的except子句。然后繼續(xù)執(zhí)行try語句之后的代碼。
如果發(fā)生了一個異常,在except子句中沒有與之匹配的分支,它就會傳遞到上一級try語句中。
如果最終仍找不到對應的處理語句,它就成為一個未處理異常,終止程序運行,顯示提示信息。一個try語句可能包含多個 except 子句,分別指定處理不同的異常
try…except語句可以帶有一個else子句,該子句只能出現(xiàn)在所有 except 子句之后。當 try 語句沒有拋出異常時,需要執(zhí)行一些代碼,可以使用這個子句
在異常名(列表)之后,也可以為 except 子句指定一個變量。這個變量綁定于一個異常實例,它存儲在instance.args的參數(shù)中
拋出異常
raise語句允許程序員強制拋出一個指定的異常
用戶自定義異常
在程序中可以通過創(chuàng)建新的異常類型來命名自己的異常
異常類通常應該直接或間接的從Exception類派生
定義清理行為
不管有沒有發(fā)生異常,finally子句在程序離開try后都一定會被執(zhí)行。當try語句中發(fā)生了未被except捕獲的異常(或者它發(fā)生在except或else子句中),在finally子句執(zhí)行完后它會被重新拋出。try語句經(jīng)由break,continue或return語句退 出也一樣會執(zhí)行finally子句
預定義清理行為
類
Python 的類機制通過最小的新語法和語義在語言中實現(xiàn)了類。
它是 C++ 或者 Modula-3 語言中類機制的混合
類的大多數(shù)重要特性都被完整的保留下來:類繼承機制允許多重繼承,派生類可以覆蓋(override)基類中的任何方法或類,可以使用相同的方法名稱調(diào)用基類的方法。對象可以包含任意數(shù)量的私有數(shù)據(jù)
Python 作用域和命名空間
命名空間是從命名到對象的映射
當前命名空間主要是通過 Python 字典實現(xiàn)的,不過通常不關心具體的實現(xiàn)方式
不同命名空間中的命名沒有任何聯(lián)系,用戶必須以模塊名為前綴來引用它們
Python 中任何一個“.”之后的命名為屬性,例如,表達式z.real中的real是對象z的一個屬性
表達式modname.funcname中,modname是一個模塊對象,funcname是它的一個屬性
模塊的屬性和模塊中的全局命名有直接的映射關系:它們共享同一命名空間
屬性可以是只讀過或?qū)懙?#xff0c;可寫的屬性也可以用del語句刪除
例如:delmodname.the_answer會從modname對象中刪除the_answer屬性
不同的命名空間在不同的時刻創(chuàng)建,有不同的生存期
模塊的全局命名空間在模塊定義被讀入時創(chuàng)建,通常,模塊命名空間也會一直保存到解釋器退出
包含內(nèi)置命名的命名空間在 Python 解釋器啟動時創(chuàng)建,會一直保留,不被刪除
由解釋器在最高層調(diào)用執(zhí)行的語句,不管它是從腳本文件中讀入還是來自交互式輸入,都是__main__模塊的一部分,所以它們也擁有自己的命名空間(內(nèi)置命名也同樣被包含在一個模塊中,它被稱作builtins)。
當調(diào)用函數(shù)時,就會為它創(chuàng)建一個局部命名空間,并且在函數(shù)返回或拋出一個并沒有在函數(shù)內(nèi)部處理的異常時被刪除
作用域就是一個 Python 程序可以直接訪問命名空間的正文區(qū)域。
通常,局部作用域引用當前函數(shù)的命名
在函數(shù)之外,局部作用域與全局使用域引用同一命名空間:模塊命名空間。
類定義也是局部作用域中的另一個命名空間。
一個定義于某模塊中的函數(shù)的全局作用域是該模塊的命名空間,而不是該函數(shù)的別名被定義或調(diào)用的位置
如果沒有使用global語法,其賦值操作總是在最里層的作用域。賦值不會復制數(shù)據(jù),只是將命名綁定到對象
特別是import語句和函數(shù)定義將模塊名或函數(shù)綁定于局部作用域(可以使用global語句將變量引入到全局作用域)。
global語句用以指明某個特定的變量為全局作用域,并重新綁定它。
nonlocal語句用以指明某個特定的變量為封閉作用域,并重新綁定它
類定義語法
類的定義就像函數(shù)定義(def語句),要先執(zhí)行才能生效
classClassName:.
.
.
進入類定義部分后,會創(chuàng)建出一個新的命名空間,作為局部作用域,所有的賦值成為這個新命名空間的局部變量。特別是函數(shù)定義在此綁定了新的命名
類定義完成時(正常退出),就創(chuàng)建了一個類對象
原始的局部作用域(類定義引入之前生效的那個)得到恢復,類對象在這里綁定到類定義頭部的類名(
類對象
類對象支持兩種操作:屬性引用和實例化
屬性引用使用和 Python 中所有的屬性引用一樣的標準語法:obj.name。類對象創(chuàng)建后,類命名空間中所有的命名都是有效屬性名
__doc__也是一個有效的屬性,返回類的文檔字符串
類的實例化使用函數(shù)符號,只要將類對象看作是一個返回新的類實例的無參數(shù)函數(shù)即可
x =MyClass()以上創(chuàng)建了一個新的類實例并將該對象賦給局部變量x
很多類都傾向于將對象創(chuàng)建為有初始狀態(tài)的。因此類可能會定義一個名為__init__()的特殊方法
def__init__(self):self.data = []
類定義了__init__()方法的話,類的實例化操作會自動為新創(chuàng)建的類實例調(diào)用__init__()方法
__init__()方法可以有參數(shù),參數(shù)通過__init__()傳遞到類的實例化操作上
classComplex:def__init__(self,realpart,imagpart):self.r =realpart
self.i =imagpart
x =Complex(3.0,-4.5)x.r,x.i
實例對象
實例對象唯一可用的操作就是屬性引用
和局部變量一樣,數(shù)據(jù)屬性不需要聲明,第一次使用時它們就會生成。
另一種為實例對象所接受的引用屬性是方法。方法是“屬于”一個對象的函數(shù)
實例對象的有效名稱依賴于它的類
按照定義,類中所有(用戶定義)的函數(shù)對象對應它的實例中的方法
方法對象
通常,方法通過右綁定方式調(diào)用,x.f()
方法的特別之處在于實例對象作為函數(shù)的第一個參數(shù)傳給了函數(shù)
通常,以n個參數(shù)的列表去調(diào)用一個方法就相當于將方法的對象插入到參數(shù)列表的最前面后,以這個列表去調(diào)用相應的函數(shù)
引用非數(shù)據(jù)屬性的實例屬性時,會搜索它的類。如果這個命名確認為一個有效的函數(shù)對象類屬性,就會將實例對象和函數(shù)對象封裝進一個抽象對象:這就是方法對象
以一個參數(shù)列表調(diào)用方法對象時,它被重新拆封,用實例對象和原始的參數(shù)列表構造一個新的參數(shù)列表,然后函數(shù)對象調(diào)用這個新的參數(shù)列表
類和實例變量
一般來說,實例變量用于對每一個實例都是唯一的數(shù)據(jù),類變量用于類的所有實例共享的屬性和方法
一些說明
數(shù)據(jù)屬性會覆蓋同名的方法屬性
大寫方法名稱的首字母,使用一個唯一的小字符串(也許只是一個下劃線)作為數(shù)據(jù)屬性名稱的前綴,或者方法使用動詞而數(shù)據(jù)屬性使用名詞
數(shù)據(jù)屬性可以被方法引用,也可以由一個對象的普通用戶(客戶)使用
換句話說,類不能用來實現(xiàn)純凈的數(shù)據(jù)類型
事實上,Python 中不可能強制隱藏數(shù)據(jù)
命名約定可以避免很多麻煩
從方法內(nèi)部引用數(shù)據(jù)屬性(或其他方法)并沒有快捷方式
一般,方法的第一個參數(shù)被命名為self。這僅僅是一個約定:對 Python 而言,名稱self絕對沒有任何特殊含義類屬性的任何函數(shù)對象都為那個類的實例定義了一個方法
函數(shù)定義代碼不一定非得定義在類中:也可以將一個函數(shù)對象賦值給類中的一個局部變量
方法可以像引用普通的函數(shù)那樣引用全局命名。與方法關聯(lián)的全局作用域是包含類定義的模塊。
(類本身永遠不會做為全局作用域使用
每個值都是一個對象,因此每個值都有一個 類(class) (也稱為它的 類型(type) ),它存儲為object.__class__
繼承
派生類的定義如下所示
classDerivedClassName(BaseClassName):.
.
.
命名BaseClassName(示例中的基類名)必須與派生類定義在一個作用域內(nèi)。除了類,還可以用表達式,基類定義在另一個模塊中時這一點非常有用
classDerivedClassName(modname.BaseClassName):構造派生類對象時,就記住了基類
如果在類中找不到請求調(diào)用的屬性,就搜索基類。如果基類是由別的類派生而來,這個規(guī)則會遞歸的應用上去
方法引用按如下規(guī)則解析:搜索對應的類屬性,必要時沿基類鏈逐級搜索,如果找到了函數(shù)對象這個方法引用就是合法的
派生類可能會覆蓋其基類的方法。因為方法調(diào)用同一個對象中的其它方法時沒有特權,基類的方法調(diào)用同一個基類的方法時,可能實際上最終調(diào)用了派生類中的覆蓋方法
派生類中的覆蓋方法可能是想要擴充而不是簡單的替代基類中的重名方法
Python 有兩個用于繼承的函數(shù):
函數(shù)isinstance()用于檢查實例類型:isinstance(obj,int)只有在obj.__class__是int或其它從int繼承的類型
函數(shù)issubclass()用于檢查類繼承:issubclass(bool,int)為True,因為bool是int的子類。
然而,issubclass(float,int)為False,因為float不是int的子類
多繼承
Python 同樣有限的支持多繼承形式
classDerivedClassName(Base1,Base2,Base3):.
super()可以動態(tài)的改變解析順序
為了防止重復訪問基類,通過動態(tài)的線性化算法,每個類都按從左到右的順序特別指定了順序,每個祖先類只調(diào)用一次,這是單調(diào)的(意味著一個類被繼承時不會影響它祖先的次序)
私有變量
有一個變通的訪問用于大多數(shù) Python 代碼:以一個下劃線開頭的命名(例如_spam)會被處理為 API 的非公開部分(無論它是一個函數(shù)、方法或數(shù)據(jù)成員)。它會被視為一個實現(xiàn)細節(jié),無需公開
name mangling(命名編碼)
任何形如__spam的標識(前面至少兩個下劃線,后面至多一個),被替代為_classname__spam,去掉前導下劃線的classname即當前的類名。此語法不關注標識的位置,只要求在類定義內(nèi)
名稱重整是有助于子類重寫方法,而不會打破組內(nèi)的方法調(diào)用
classMapping:def__init__(self,iterable):self.items_list = []self.__update(interable)defupdate(self,interable):foritem ininterable:self.items_list.append(item)__update =update
classMappingSubclass(Mapping):defupdate(self,keys,values):foritem inzip(keys,values):self.items_list.append(item)需要注意的是編碼規(guī)則設計為盡可能的避免沖突,被認作為私有的變量仍然有可能被訪問或修改
要注意的是代碼傳入exec(),eval()時不考慮所調(diào)用的類的類名,視其為當前類,這類似于global語句的效應,已經(jīng)按字節(jié)編譯的部分也有同樣的限制。這也同樣作用于getattr(),setattr()和delattr(),像直接引用__dict__一樣。
補充
將一組已命名的數(shù)據(jù)項綁定在一起。一個空的類定義可以很好的實現(xiàn)它
classEmployee:passjohn =Employee()# Create an empty employee record# Fill the fields of the recordjohn.name ='John Doe'john.dept ='computer lab'john.salary =1000實例方法對象也有屬性:m.__self__是一個實例方法所屬的對象,而m.__func__是這個方法對應的函數(shù)對象
異常也是類
用戶自定義異常也可以是類。利用這個機制可以創(chuàng)建可擴展的異常體系
以下是兩種新的,有效的(語義上的)異常拋出形式,使用raise語句:
raiseClass
raiseInstance
第一種形式中,Class必須是type或其派生類的一個實例。第二種形式是以下形式的簡寫
raiseClass()
發(fā)生的異常其類型如果是except子句中列出的類,或者是其派生類,那么它們就是相符的(反過來說--發(fā)生的異常其類型如果是異常子句中列出的類的基類,它們就不相符)
classB(Exception):passclassC(B):passclassD(C):passforcls in[B,C,D]:try:raisecls()exceptD:print("D")exceptC:print("C")exceptB:print("B")
打印一個異常類的錯誤信息時,先打印類名,然后是一個空格、一個冒號,然后是用內(nèi)置函數(shù)str()將類轉(zhuǎn)換得到的完整字符串
迭代器
大多數(shù)容器對象都可以用for遍歷:
迭代器的用法在 Python 中普遍而且統(tǒng)一
在后臺,for語句在容器對象中調(diào)用iter()。該函數(shù)返回一個定義了__next__()方法的迭代器對象,它在容器中逐一訪問元素。沒有后續(xù)的元素時,__next__()拋出一個StopIteration異常通知for語句循環(huán)結(jié)束
給自己的類添加迭代器行為
定義一個__iter__()方法,使其返回一個帶有__next__()方法的對象
如果這個類已經(jīng)定義了__next__(),那么__iter__()只需要返回self:
classReverse:"""Iterator for looping over a sequence backwards."""def__init__(self,data):self.data =data
self.index =len(data)def__iter__(self):returnselfdef__next__(self):ifself.index ==0:raiseStopIterationself.index =self.index -1returnself.data[self.index]
生成器
Generator是創(chuàng)建迭代器的簡單而強大的工具。它們寫起來就像是正規(guī)的函數(shù),需要返回數(shù)據(jù)的時候使用yield語句。每次next()被調(diào)用時,生成器回復它脫離的位置(它記憶語句最后一次執(zhí)行的位置和所有的數(shù)據(jù)值)
defreverse(data):forindex inrange(len(data)-1,-1,-1):yielddata[index]forchar inreverse('golf'):print(char)基于類的迭代器,它能作的每一件事生成器也能作到
因為自動創(chuàng)建了__iter__()和__next__()方法,生成器顯得如此簡潔
另一個關鍵的功能在于兩次執(zhí)行之間,局部變量和執(zhí)行狀態(tài)都自動的保存下來
除了創(chuàng)建和保存程序狀態(tài)的自動方法,當發(fā)生器終結(jié)時,還會自動拋出StopIteration異常
生成器表達式
有一個例外。模塊對象有一個隱秘的只讀對象,名為__dict__,它返回用于實現(xiàn)模塊命名空間的字典,命名__dict__是一個屬性而非全局命名。顯然,使用它違反了命名空間實現(xiàn)的抽象原則,應該被嚴格限制于調(diào)試中。
來自
https://www.runoob.com/manual/pythontutorial3/docs/html/appetite.html
總結(jié)
以上是生活随笔為你收集整理的python语法详解大全_笔记:Python 语法要点汇总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python字符串数组中最短的_pyth
- 下一篇: dalsa线扫相机调试文档_线阵相机调试