### 5. 表達式
這一章解釋Python中表達式的各個組成部分的含義。
**關于語法:**在這一章及隨后的章節中所用到的擴展BNF語法符號將用于講述語法,而不是詞法分析。當一個語法規則具有這樣的形式
~~~
name ::= othername
~~~
且沒有給出語義,那么這種形式的name語義與othername相同。
### 5.1. 算術轉換
當下面算術操作符的描述使用短語“數字參數被轉換為一個共同的類型”時,這些參數將使用[*隱式轉換規則*](#)列出的規則做隱式轉換。如果兩個參數都是標準的數字類型,那么運用下面的隱式轉換:
- 如果任意一個參數是復數,將另外一個轉換成復數;
- 否則,如果任意一個參數是浮點數,則將另外一個轉換為浮點數;
- 否則,如果任意一個是長整數,則將另外一個轉換成長整數;
- 否則,兩個參數必定都是普通的整數且不必要轉換。
某些特定的操作符適用其它的一些規則(例如,‘%’操作符左邊的字符串參數)。解釋器的擴展可以定義它們自己的轉換規則。
### 5.2. 原子
原子是表達式最基礎的元素。最簡單的原子是標識符和字面值。在引號、圓括號、方括號或者花括號中的封閉形式在語法上也被分類為原子。原子的語法為:
~~~
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display
| generator_expression | dict_display | set_display
| string_conversion | yield_atom
~~~
#### 5.2.1. 標識符(名稱)
一個以原子出現的標識符是一個名稱。詞法定義請參看[*標識符和關鍵字*](#)小節,名稱和綁定的文檔請參看[*名稱和綁定*](#)小節。
當名稱綁定到一個對象上時,對該原子的求值將產生那個對象。當名稱沒有綁定時,試圖對它求值將拋出[NameError](# "exceptions.NameError")異常。
**私有變量名稱的改編:**當出現在類定義中的標識符以兩個或多個下劃線字符開始且不是以兩個或多個下劃線結束,它被認為是那個類的*私有名稱*。在為它們生成代碼之前,私有名稱被轉換為更長的形式。該轉換在名稱在前面插入類的名稱,前導的下滑線被刪除并插入一個單一的下劃線。例如,出現在類Ham中的標識符__spam將被轉換成_Ham__spam。這種轉換與標識符使用的語法上下文無關。如果轉換后的名稱過長(超過255個字符),將可能發生與具體實現有關的截斷。如果類的名稱只由下劃線組成,則不會轉換。
#### 5.2.2. 字面值
Python支持字符串字面值和各種數值字面值:
~~~
literal ::= stringliteral | integer | longinteger
| floatnumber | imagnumber
~~~
在浮點數和虛數(復數)情況下,可能只是近似值。詳細信息參見[*字面值*](#)一節。
所有的字面值都是不可變數據類型,因此對象的ID不如它的值重要。多次計算具有相同值的字面值(無論是程序文本中相同的出現還是不同的出現)得到的既可能是同一個對象也可能是具有相同值的不同對象。
#### 5.2.3. 圓括號式
圓括號式是包含在圓括號中的一個可選表達式序列:
~~~
parenth_form ::= "(" [expression_list] ")"
~~~
圓括號中的表達式序列產生的就是該表達式序列產生的內容:如果序列包含至少一個逗號,那么它產生一個元組;否則,它產生組成表達式序列的那個單一表達式。
空的圓括號對產生空的元組對象;因為元組是不可變的,字面值的規則同樣適用(例如空元組的兩次出現可能產生相同或不同的對象)。
注意元組不是通過圓括號而是逗號操作符形成。有個例外是空元組,它*必須*要有圓括號 — 允許表達式中出現沒有括號的“空白”將導致歧義并使得常見的拼寫錯誤無法發現。
#### 5.2.4. 列表表示式
列表表示式是在方括號中的可以為空的一系列表達式:
~~~
list_display ::= "[" [expression_list | list_comprehension] "]"
list_comprehension ::= expression list_for
list_for ::= "for" target_list "in" old_expression_list [list_iter]
old_expression_list ::= old_expression [("," old_expression)+ [","]]
old_expression ::= or_test | old_lambda_expr
list_iter ::= list_for | list_if
list_if ::= "if" old_expression [list_iter]
~~~
列表的表示式產生一個新的列表對象。它的內容通過提供一個表達式序列或者一個列表推導式指定。當提供的是一個逗號分隔的表達式序列時,對它的元素從左向右求值并按此順序放入列表對象中。當提供的是一個列表推導式時,它由一個單一的表達式后面跟著至少一個[for](#)子句和零個或多個[for](#)或者[if](#)子句組成。在這種情況下,新的列表的元素是由[for](#)或者[if](#)子句塊產生,這些子句塊從左向右嵌套,且當到達最內層的代碼塊時對表達式求值以產生一個列表元素[[1]](#)。
#### 5.2.5. 集合和字典的表示式
對于構造集合和字典,Python提供特殊的語法叫做“表示式",它們有兩種方式:
- 容器的內容被顯式地列出,或者
- 它們通過一系列循環和過濾指令計算得到,這種方式叫做*推導式*。
推導式常見的語法元素為:
~~~
comprehension ::= expression comp_for
comp_for ::= "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" expression_nocond [comp_iter]
~~~
推導式由一個單一的表達式后面跟隨至少一個[for](#)子句加上零個或多個[for](#)或者[if](#)子句。在這種情況下,新的列表的元素是由[for](#)或者[if](#)子句塊產生,這些子句塊從左向右嵌套,且當到達最內層的代碼塊時對表達式求值以產生一個列表元素。
注意,推導式在一個單獨的作用域中執行,所以在目標序列中賦值的名稱不會“泄露”到外圍的作用域中。
#### 5.2.6. 生成器表達式
生成器表達式是在圓括號中的一個簡潔的生成器符號:
~~~
generator_expression ::= "(" expression comp_for ")"
~~~
生成器表達式產生一個新的生成器對象。它的語法與推導式相同,只是它位于圓括號而不是方括號或花括號中。
生成器表達式中使用的變量在為生成器對象調用__next__()方法時才會惰性地求值(與普通的生成器方式相同)。但是,最左邊的[for](#)子句會立即計算,所以它產生的錯誤可以在生成器表達式代碼中的任何其它可能的錯誤之前發現。隨后的[for](#)子句不可以立即計算因為它們可能依賴于前面的[for](#)循環。例如:(x*yforxinrange(10)foryinbar(x))。
圓括號對于只有一個參數的調用可以省略。細節請參考[*調用*](#)一節。
#### 5.2.7. 字典表示式
字典表示式是在花括號中的可以為空的一系列鍵/值對。
~~~
dict_display ::= "{" [key_datum_list | dict_comprehension] "}"
key_datum_list ::= key_datum ("," key_datum)* [","]
key_datum ::= expression ":" expression
dict_comprehension ::= expression ":" expression comp_for
~~~
字典表示式產生一個新的字典對象。
如果給出逗號分隔的鍵/值對序列,將從左向右對它們求值以定義字典中項:用每個鍵對象作為字典的鍵并存儲對應的值。這意味著你可以在鍵/值序列中多次指定相同的鍵,但是該鍵最終對應的字典的值將是最后給出的那個值。
字典推導式,與列表和集合推導式相比,需要兩個冒號分隔的表達式并在后面跟隨通常的“for”和“if”子句。當推導執行時,產生的鍵和值以它們生成的順序插入到新的字典中。
鍵的類型的限制在前面的[*標準類型的層次*](#)一節中有列出。(簡要地講,鍵的類型應該是[*可哈希的*](#),即排除所有可變的對象。)重復的鍵之間的沖突不會被檢測到;一個給定的鍵的最后的值(表示式中最右邊的值)將獲勝。
#### 5.2.8. 集合表示式
集合表示式通過花括號表明,與字典表示式的區別是缺少冒號分隔的鍵和值:
~~~
set_display ::= "{" (expression_list | comprehension) "}"
~~~
集合表示式產生一個新的可變集合對象,它的內容可以通過一個表達式序列或者一個推導式指定。當提供的是一個逗號分隔的表達式序列時,將從左向右計算它的元素并添加到集合對象中。當提供的是一個推導式時,集合根據推導式產生的元素構造。
不可以用{}構造一個空集合;該字面值構造一個空的字典。
#### 5.2.9. 字符串轉換式
字符串轉換式是包含在反引號中的一個表達式序列:
~~~
string_conversion ::= "`" expression_list "`"
~~~
字符串轉換式計算包含的表達式序列并根據結果對象類型的特定規則將結果對象轉換成一個字符串。
如果對象是一個字符串、一個數字、None或者一個只包含這些類型的對象,那么結果字符串將是一個合法的Python表達式,它可以傳遞給內建的[eval()](# "eval")函數以產生一個具有相同值的表達式(或者近似值,如果調用的是浮點數)。
(特別地,字符串轉換式會添加引號并將“古怪”的字符轉換為轉義的序列,這些序列打印出來是安全的。)
遞歸的對象(例如,直接或間接包含自身引用的列表或字典)使用...來表示一個遞歸的引用,其結果不可以傳遞給[eval()](# "eval")以獲得一個相等的值(將引發[SyntaxError](# "exceptions.SyntaxError"))。
內建函數[repr()](# "repr: Alternate repr() implementation with size limits.")對其參數所做的轉換與將它放入圓括號和反引號中完全相同。內建函數[str()](# "str")完成類似但更友好的轉換。
#### 5.2.10. Yield 表達式
~~~
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list]
~~~
2.5 版中新增。
[yield](#)表達式只用于定義生成器函數,且只能用于函數的定義體中。在函數定義中使用[yield](#)表達式就可以充分使得該定義創建一個生成器函數而不是普通的函數。
當調用生成器函數時,它返回一個稱為生成器的迭代器。然后該生成器控制生成器函數的執行。當調用生成器的其中一個方法時,執行開始。此時,執行會行進到第一個[yield](#)表達式,在那里執行被掛起并返回[expression_list](#)的值給生成器的調用者。掛起的意思是保存所有的局部狀態,包括當前局部變量的綁定、指令的指針和內部的計算棧。當通過調用生成器的一個方法來恢復執行時,函數可以準確地繼續執行就好像[yield](#)表達式只是一個外部的調用。恢復執行后[yield](#)表達式的值取決于恢復執行的方法。
所有這些使得生成器函數與協程非常類似;它們可以yield多次,它們有多個入口點且它們的執行可以掛起。唯一的區別是生成器函數不可以控制yield之后執行應該從何處繼續;控制始終被轉讓給生成器的調用者。
##### 5.2.10.1. ?生成器迭代器的方法
該小節講述生成器迭代器的方法。它們可用于控制生成器函數的執行。
注意當生成器已經在執行時調用下面的任何一個生成器方法都將引發[ValueError](# "exceptions.ValueError")異常。
*class*generatorgenerator.next()
開始生成器函數的執行或者在最后一次執行的[yield](#)表達式處恢復執行。當生成器函數使用[next()](# "next")方法恢復執行時,當前的[yield](#)表達式始終[None](# "None")。然后執行繼續行進到下一個[yield](#)表達式,在那里生成器被再次掛起并返回[expression_list](#)的值給[next()](# "next")的調用者。如果生成器退出時沒有yield另外一個值,則引發一個[StopIteration](# "exceptions.StopIteration")異常。
.generator.send(*value*)
恢復執行并“發送”一個值到生成器中。該value參數成為當前[yield](#)表達式的結果。[send()](# "generator.send")方法返回生成器yield的下一個值,如果生成器退出時沒有yield另外一個值則引發[StopIteration](# "exceptions.StopIteration")。當調用[send()](# "generator.send")用于開始生成器的執行時,它必須以[None](# "None")作為參數進行調用,因為沒有接受該值的[yield](#)表達式。
generator.throw(*type*[, *value*[, *traceback*]])
在生成器暫停的地方引發一個type類型的異常,并返回生成器函數yield的下一個值。如果生成器在退出時沒有yield一個值,則引發[StopIteration](# "exceptions.StopIteration")異常。如果生成器函數沒有捕獲傳遞進來的異常或者引發一個不同的異常,那么該異常將傳播到調用者。
generator.close()
在生成器函數暫停的地方引發一個[GeneratorExit](# "exceptions.GeneratorExit")。如果生成器函數此后引發[StopIteration](# "exceptions.StopIteration")(正常退出或者由于已經正在關閉)或者[GeneratorExit](# "exceptions.GeneratorExit")(沒有捕獲該異常),close會返回到調用者。如果生成器yield一個值,則引發一個[RuntimeError](# "exceptions.RuntimeError")。如果生成器引發其它任何異常,它會被傳播到調用者。如果生成器已經由于異常退出或正常退出,[close()](# "generator.close")不會做任何事情。
這里有個簡單的例子演示生成器和生成器函數的行為:
~~~
>>> def echo(value=None):
... print "Execution starts when 'next()' is called for the first time."
... try:
... while True:
... try:
... value = (yield value)
... except Exception, e:
... value = e
... finally:
... print "Don't forget to clean up when 'close()' is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when 'next()' is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.
~~~
另請參閱
[**PEP 0342**](http://www.python.org/dev/peps/pep-0342) - 通過增強的生成器實現協程增強生成器API和語法的提議,使得它們可以作為簡單的協程使用。
### 5.3. 初級操作
初級操作表示語言中綁定性最高的操作。它們的語法是:
~~~
primary ::= atom | attributeref | subscription | slicing | call
~~~
#### 5.3.1. 屬性引用
屬性引用是一個初級操作,后面跟隨一個句號和一個名稱:
~~~
attributeref ::= primary "." identifier
~~~
primary必須是一個支持屬性引用類型的對象,例如模塊、列表和實例。接著該對象被要求生成名稱為identifier的屬性。如果該屬性不可訪問,則拋出[AttributeError](# "exceptions.AttributeError")異常。否則,生成的對象的類型和值取決于該對象。對相同屬性的多次求值可能產生不同的對象。
#### 5.3.2. 下標
下標選擇序列(字符串、元組或列表)或者映射(字典)對象的一個元素:
~~~
subscription ::= primary "[" expression_list "]"
~~~
primary必須是一個序列或者映射類型的對象。
如果primary是一個映射,那么expression_list必須是一個對象,其值為映射的一個鍵,該下標選擇映射中對應于該鍵的值。(expression_list是一個元組除非它只有一個元素。)
如果primary是一個序列,那么expression_list必須是一個普通的整數。如果該值是負數,則加上該序列的長度(所以,x[-1]選擇x的最后一個元素。)結果值必須是一個小于序列元素個數的非負整數,下標操作選擇索引為該值的元素(從零開始計數)。
字符串的元素為字符。字符不是一個單獨的數據類型而是只有一個字符的字符串。
#### 5.3.3. 切片
切片選擇序列對象(例如,字符串、元組和列表)中一個范圍內的元素。切片可以用作表達式或者作為賦值和[del](#)語句的目標。切片的語法:
~~~
slicing ::= simple_slicing | extended_slicing
simple_slicing ::= primary "[" short_slice "]"
extended_slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice | ellipsis
proper_slice ::= short_slice | long_slice
short_slice ::= [lower_bound] ":" [upper_bound]
long_slice ::= short_slice ":" [stride]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
ellipsis ::= "..."
~~~
這里的形式語法有歧義:expession_list看上去也像slice_list,所以任何下標也可以解釋為切片。為了不引入更復雜的語法,通過定義在這種情況下解釋為下標優先于解釋為切片來消除歧義(如果slice_list不包含proper_slice和ellipse也屬于這種情況)。類似地,當slice_list只有一個short_slice且沒有末尾的逗號時,解釋為簡單切片要優先于解釋為擴展切片。
簡單切片的語義如下。primary必須是一個序列對象。下界和上界表達式,如果存在,必須是普通的整數;默認分別是零和sys.maxint。如果有一個是負數,則將它加上序列的長度。切片選擇所有索引為*k*的元素,其中i<=k<j且*i*和*j*是指定的下界和上界。它可能是一個空的序列。如果*i*或者*j*位于合法的索引范圍之外不會出錯(這些元素不存在所以它們不會被選擇)。
擴展切片的語法如下。primary必須是一個映射對象,它以從slice_list構造的鍵做索引,如下所示。如果slice_list包含至少一個逗號,則鍵是一個包含slice_item轉換的元組;否則,long_slice作為鍵。slice_item是一個表達式時,轉換就是那個表達式。slice_item是ellipsis時,轉換為內建的Ellipsis對象。proper_slice的轉換是一個切片對象(參閱[*標準類型的層次*](#)),它的start、stop和step屬性分別是表達式lower_bound、upper_bound和stride的值,沒有的表達式用None代替。
#### 5.3.4. 調用
調用是指用一個可以為空的[*參數*](#)序列調用一個可調用對象(例如,一個[*函數*](#)):
~~~
call ::= primary "(" [argument_list [","]
| expression genexpr_for] ")"
argument_list ::= positional_arguments ["," keyword_arguments]
["," "*" expression] ["," keyword_arguments]
["," "**" expression]
| keyword_arguments ["," "*" expression]
["," "**" expression]
| "*" expression ["," "*" expression] ["," "**" expression]
| "**" expression
positional_arguments ::= expression ("," expression)*
keyword_arguments ::= keyword_item ("," keyword_item)*
keyword_item ::= identifier "=" expression
~~~
在位置參數和關鍵字參數之后可以存在一個末尾的逗號而不影響語義。
primary必須是一個可調用的對象(用戶定義的函數、內建的函數、內建對象的方法、類對象、類實例的方法以及某些類實例自己也是可調用的;Python的擴展可以定義額外的可調用對象類型)。所有的參數表達式都將在調用發生之前求值。關于形式[*參數*](#)列表的語法請參考[*函數的定義*](#)一節。
如果存在關鍵字參數,它們首先被轉換為位置參數,如下所述。首先,創建一個沒有填充的空位序列用于形參。如果有N個位置參數,則它們被放置在前N個空位中。下一步,對于每個關鍵字參數,用標識符決定對應的位置(如果標識符與第一個形參的名稱相同,則使用第一個位置,以此類推)。如果該位置已經被填充,則引發一個[TypeError](# "exceptions.TypeError")異常。否則,將該參數的值放入該位置并填充它(即使該表達式是None,它也會填充該位置)。當處理完所有的參數時,仍然沒有填充的位置將用來自函數定義的對應默認值填充。(默認值只在函數定義時計算一次;因此,用于默認值的可變對象例如列表或字典將被所有沒有指定對應位置參數值的調用共享;通常應該避免這點。)如果有沒有填充的空位且沒有指定默認值,則引發一個[TypeError](# "exceptions.TypeError")異常。否則,使用這些填滿的位置作為調用的參數序列。
**CPython實現細節:**一種實現可以提供這樣的內建函數,它的位置參數沒有名稱,因此不可以通過關鍵字提供,即使它們由于文檔的需要而被“命名”。在CPython中,那些用C實現并使用[PyArg_ParseTuple()](# "PyArg_ParseTuple")解析參數的函數就是這種情況。
如果位置參數的個數多于形參,則引發一個[TypeError](# "exceptions.TypeError")異常,除非存在一個使用*identifier語法的形參;在這種情況下,該形參接收一個包含多余位置參數的元組(如果沒有多余的位置參數則為空元組)。
如果有任何關鍵字參數沒有對應的形參名稱,則引發一個[TypeError](# "exceptions.TypeError")異常,除非存在一個使用**identifier語法的形參;在這種情況下,該形參接收一個包含多余的關鍵字參數的字典(使用關鍵字作為鍵,參數值作為對應的值),如果沒有多余的關鍵字參數則為一個(新的)空字典。
如果*expression語法出現在函數調用中,那么expression必須是一個可迭代器。來自該可迭代器的元素被當作額外的位置參數;如果位置參數為*x1*, ..., *xN*且expression求值為一個序列*y1*, ..., *yM*,那么它等同于用M+N個位置參數*x1*, ..., *xN*, *y1*, ..., *yM*的調用。
這種方式的后果是雖然*expression可以出現在某些關鍵字參數*之后*,但是它將在關鍵字參數(以及**expression參數–見下文)*之前*處理。所以:
~~~
>>> def f(a, b):
... print a, b
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2
~~~
關鍵字參數和*expression語法都在同一個調用中使用很不常見,所以實踐中這種困惑不會出現。
如果**expression語法出現在函數調用中,那么expression必須是一個映射,它的內容將被當作額外的關鍵字參數。某個關鍵字在expression和顯式的關鍵字參數中都出現的情況下,將引發[TypeError](# "exceptions.TypeError")異常。
使用*identifier或者**identifier語法的形參不可以作為位置參數的槽位或者關鍵字參數的名稱使用。使用(sublist)語法的形參不可以作為關鍵字參數的名稱使用;最外層的sublist對應于單一的一個未命令參數槽位,在所有其它參數的處理完成之后參數的值使用普通的元組賦值規則賦值給sublist。
一個調用永遠返回某個值,即使可能為None,除非它引發一個異常。該值如何計算取決于可調用對象的類型。
如果它是—
一個用戶定義的函數:
該函數的代碼塊將被執行,并將參數列表傳遞給它。代碼塊所做的第一件事是將綁實參與參數定;這在[*函數的定義*](#)一節有講述。當代碼塊執行一條[return](#)時,它表示該函數調用的返回值。
一個內建的函數或方法:
結果取決于解釋器;內建函數和方法的描述請參見[*內建的函數*](#) 。
一個類對象:
返回該類的一個新的實例。
一個類實例的方法:
調用對應的用戶自定義的函數,參數列表比調用的參數列表多一個元素:實例成為第一個參數。
一個類實例:
該類必須定義一個[__call__()](# "object.__call__")方法;效果和調用該方法一樣。
### 5.4. 乘方操作符
乘方操作符的綁定性比它左側的一元操作符高;比它右側的一元操作符綁定性低。其語法是:
~~~
power ::= primary ["**" u_expr]
~~~
因此,在一個沒有括號的乘方和一元操作符序列中,操作符從右向左計算(這不會約束操作數的計算順序):-1**2的結果是-1。
乘方操作符的語義與用兩個參數調用內建的[pow()](# "pow")函數相同:它產生左側參數的右側參數次冪。其數值參數首先被轉換成相同的類型。結果的類型是強制轉換后的參數類型。
操作符的類型不一樣時,運用二元算術操作符的強制轉換規則。對于整數和長整數,結果的類型與(強制轉換后的)操作數類型相同,除非第二個參數為負數;在這種情況下,所有的參數被轉換成浮點數并返回浮點數結果。例如,10**2返回100,但是10**-2返回0.01。(最后的這個特性在Python2.2中添加。在Python2.1和之前的版本中,如果兩個參數都是整數且第二個參數為負,則會引發一個異常)。
0.0的負數乘方將導致[ZeroDivisionError](# "exceptions.ZeroDivisionError")。負數的小數次冪將導致[ValueError](# "exceptions.ValueError")。
### 5.5. 一元算術和位操作
所有的一元算術和位操作具有相同的優先級:
~~~
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
~~~
一元-(負)操作符產生其數值參數的負值。
一元+(正)操作符產生其數值參數保持不變。
一元~(反)操作符產生其普通整數和長整數參數按位取反的值。x按位取反定義為-(x+1)。它只適用于整數數值。
在這三種情形中,如果參數的類型不合適,都將引發[TypeError](# "exceptions.TypeError")異常。
### 5.6. 二元算術操作
二元算術操作具有傳統的優先級。注意這里的某些操作同樣適用于一些非數值類型。除了乘方操作符,有兩個優先級,一個針對乘法操作符,一個針對加法操作符:
~~~
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr
| m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
~~~
*(乘法)操作符產生它參數的乘積。其參數必須都是數值,或者一個是整數(普通整數或長整數)另外一個是序列。在前一種情況下,數值會被轉換成一個相同的類型然后一起相乘。在后一種情況下,將進行序列的重復操作;負的重復值將產生一個空的序列。
/(除法)和//(整除)操作符產生它們參數的商。其數值參數首先被轉換成相同的類型。普通整數或者長整數除法產生一個相同類型的整數;其結果是在算術除法的結果上調用“取整”函數。除以零將引發[ZeroDivisionError](# "exceptions.ZeroDivisionError")異常。
%(取模)操作符產生第一個參數除以第二個參數后的余數。其數值參數將首先被轉換成相同的類型。右邊的參數為零將引發[ZeroDivisionError](# "exceptions.ZeroDivisionError")異常。參數可以是浮點數,例如,3.14%0.7等于0.34(因為3.14等于4*0.7+0.34。)取模操作符永遠產生與第二個操作符符號相同的結果(或者為零);結果的絕對值將嚴格小于第二操作數的絕對值[[2]](#)。
整數的除法和取模操作由下面的等式相關聯:x==(x/y)*y+(x%y)。整數除法和取模同樣由內建函數[divmod()](# "divmod")相關聯:divmod(x,y)==(x/y,x%y)。這些等式對于浮點數不成立;類似的等式在x/y替換為floor(x/y)或者floor(x/y)-1時近似成立[[3]](#)。
除了執行整數的取模操作,%操作符還被字符串和unicode對象重載用于執行字符串的格式化(也叫做插值)。字符串格式化的語法在Python庫參考的[*字符串格式化*](#)一節講述。
2.3版后廢棄的內容:整除操作符、取模操作符和[divmod()](# "divmod")函數不再為復數定義。作為替代,如果合適,使用將[abs()](# "abs")函數將其轉換為浮點數。
+(加法)操作符產生其參數的和。其參數必須都是數值或者都是相同類型的序列。在前一種情況下,數值被轉換成相同的類型然后一起相加。在后一種情況下,序列被連接在一起。
-(減法)操作符產生其參數差。其參數首先被轉換成相同的類型。
### 5.7. 移位操作
移位操作的優先級低于算術操作:
~~~
shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr
~~~
這些操作符接收普通整數或者長整數作為參數。參數會被轉換成一種共同的類型。它們將第一個參數向左或向右移動第二個參數指出的位數。
右移*n*位定義為除以pow(2,n)。左移*n*位定義為乘以pow(2,n)。負的移位數目會引發[ValueError](# "exceptions.ValueError")異常。
注
在當前的實現中,要求右操作數至多為[sys.maxsize](# "sys.maxsize")。如果右操作數大于[sys.maxsize](# "sys.maxsize"),將引發[OverflowError](# "exceptions.OverflowError")異常。
### 5.8. 二元位操作
下面三種位操作具有各自不同的優先級:
~~~
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
~~~
&操作符產生按位與,它的參數必須是普通整數或長整數。參數會被轉換成一種共同的類型。
^操作符產生按位異或,它的參數必須是普通整數或長整數。參數會被轉換成一種共同的類型。
|操作符產生按位或,它的參數必須是普通整數或長整數。參數會被轉換成一種共同的類型。
### 5.9. 比較操作
與C不同,Python中所有的比較操作具有相同的優先級,并低于任何算術、移位和位操作。與C不同的還有,類似a<b<c?這樣的表達式就是數學中傳統的含義。
~~~
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
| "is" ["not"] | ["not"] "in"
~~~
比較操作產生兩個值:True 或者False。
比較操作可以任意連接,例如x<y<=z等同于x<yandy<=z,但是y只計算一次(在兩種情況中當發現x<y為假時都不會再計算z)。
形式上,如果*a*, *b*, *c*, ..., *y*, *z*是表達式且*op1*, *op2*, ..., *opN*是操作數,那么aop1bop2c...yopNz等同于aop1bandbop2cand...yopNz,不同點是每個表達式值至多計算一次。
注意aop1bop2c并不意味著*a* 和*c* 之間會有比較,所以x<y>z 是完全合法的(盡管不漂亮)。
<>和!=兩種形式時等同的;為了與C保持一致,傾向于使用!=;下面提到!=的地方同樣接受<> 。拼寫<>被認為是廢棄的。
操作符<、>、==、>=、<=和!= 比較兩個對象的值。對象不需要具有相同的類型。如果兩個都是數字,它們將被轉會成一個共同的類型。否則,不同類型的對象將*永遠*是不相等的,雖然順序是固定的但是是隨機的。你可以通過定義__cmp__方法或者像__gt__這樣更豐富的比較方法來控制非內建類型對象的比較行為,在[*Special method names*](#)一節有詳細的描述。
(這種不常見的比較定義用于簡化像排序這種操作的定義以及[in](#)和[notin](#)操作符。未來,不同類型對象的比較規則可能會改變。)
相同類型對象的比較取決于它們的類型:
-
數字按照算術意義比較。
-
字符串使用字符對應的數值(內建函數[ord()](# "ord")的結果)按字典序比較。?Unicode和八比特字符完全適用這種行為。[[4]](#)
-
元組和列表通過比較對應的項按字典序比較。這意味著若要比較結果相等,每一個元素比較的結果必須相等且兩個序列的類型必須相同并且具有相同的長度。
如果不相等,序列按照它們第一個不同的元素排序。例如,cmp([1,2,x],[1,2,y])的返回值與cmp(x,y)相同。如果對應的元素不存在,則長度較短的序列排在第一個(例如[1,2]<[1,2,3])。
-
映射(字典)當且僅當它們排好序的(鍵,值)列表相等時才相等。[[5]](#)雖然當不相等時的結果是固定的,但是具體是怎樣的結果是沒有定義的。[[6]](#)
-
其它大部分內建類型的對象是不相等的除非它們是相同的對象;一個對象是小于還是大于另外一個對象的抉擇雖然是隨機的但是在程序的一次執行中是一致的。
操作符[in](#)和[notin](#)用于測試成員資格。如果*x*?是*s*?的一個成員那么xins為真,否則為假。xnotins返回xins的否定式。成員資格測試傳統用于序列上;如果序列包含一個元素與某對象相等則該對象是這個序列的成員。然而,其它許多類型的對象不用稱為序列而支持成員資格測試也是合理的。特別地,字典(針對鍵)和集合就支持成員關系測試。
對于列表和元組類型,xiny 為真當且僅當存在一個索引*i*?使得x==y[i]為真。
對于Unicode和字符串類型,xiny為真當且僅當*x* 是*y* 的一個子串。
版本2.3 中的改變:之前,*x*要求是一個長度為1的字符串。
對于定義了[__contains__()](# "object.__contains__")方法的用戶自定義類,xiny為真當且僅當y.__contains__(x)為真。
對于沒有定義[__contains__()](# "object.__contains__")但定義[__iter__()](# "object.__iter__")的用戶自定義類,xiny為真如果某個值z在迭代y時滿足x==z。如果迭代過程中拋出異常,就好像是[in](#)拋出那個異常一樣。
最后,嘗試舊式的迭代協議:如果一個類定義了[__getitem__()](# "object.__getitem__"),xiny為真當且僅當有一個非負的整數索引*i*使得x==y[i], 且更小的索引不會引發[IndexError](# "exceptions.IndexError")異常。(如果引發了其它異常,則像是[in](#)引發了該異常)。
[notin](#)操作符定義為取與[in](#)相反的真值。
[is](#) 和[isnot](#)操作測試對象的ID:xisy當且僅當*x*和*y*是相同的對象時為真。xisnoty產生相反的真值。[[7]](#)
### 5.10. 布爾操作
~~~
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
~~~
在布爾操作的上下文中,同時在控制流語句使用表達式的時候,以下的值被解釋為假:False、None、所有類型中的數值零、空的字符串和容器(包括字符串、元組、字典和固定集合)。其它所有的值都解釋為真。(請參見[__nonzero__()](# "object.__nonzero__")?特殊方法以獲得改變這種行為的方式。)
如果操作符[not](#)的參數為假則其產生True,否則產生False。
表達式xandy首先計算*x*;如果*x*為假,則返回它的值;否則,再計算*y* 并返回結果的值。
表達式xory首先計算*x*;如果*x*為真,則返回它的值;否則,再計算*y* 并返回結果值。
(注意[and](#)和[or](#)的返回值都不局限于False和True,而是返回最后計算的參數結果。這在有些時候是有用的,例如,如果s是一個字符串,當它是空的時候應該被一個默認值替換,那么表達式sor'foo'就可以產生想要的值。因為[not](#)無論如何必須生成一個值,它不會設法返回和其參數類型相同的值,所以not'foo'生成False, 而非''。)
### 5.11. 條件表達式
在版本2.5 中新引入。
~~~
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
~~~
條件表達式(有時叫做“三元操作符”)在所有的Python操作符中具有最低的優先級。
表達式xifCelsey首先計算條件*C*(而非*not**x*);如果*C*為真,則計算*x* 并返回它的值;否則,計算*y* 并返回它的值。
關于條件表達式的更多細節,請參見[**PEP 308**](http://www.python.org/dev/peps/pep-0308)。
### 5.12. Lambda 表達式
~~~
lambda_expr ::= "lambda" [parameter_list]: expression
old_lambda_expr ::= "lambda" [parameter_list]: old_expression
~~~
Lambda表達式(有時叫做lambda形式)具有和表達式相同的地位。它們是創建匿名函數的一種快捷方式;表達式lambdaarguments:expression生成一個函數對象。此命名對象的行為類似下面定義的函數對象
~~~
def name(arguments):
return expression
~~~
關于參數列表的語法,請參見[*函數定義*](#)一節。注意lambda表達式創建的函數不可以包含語句。
### 5.13. 表達式序列
~~~
expression_list ::= expression ( "," expression )* [","]
~~~
至少包含一個逗號的表達式序列產生一個元組。元組的長度是列表中表達式的個數。表達式按從左到右的順序計算。
尾部的逗號僅僅在創建單元素元組(又叫*獨元*)時需要;在其它所有情況下,它都是可選的。
- Python 2 教程
- 1. 吊吊你的胃口
- 2. Python 解釋器
- 3. Python簡介
- 4. 控制流
- 5. 數據結構
- 6. 模塊
- 7. 輸入和輸出
- 8. 錯誤和異常
- 9. 類
- 10. 標準庫概覽
- 11. 標準庫概覽 — 第II部分
- 12.現在怎么辦?
- 13. 交互式輸入的編輯和歷史記錄
- 14. 浮點數運算:問題和局限
- Python 2 標準庫
- 1. 引言
- 2. 內建函數
- 3. 不太重要的內建函數
- 4. 內建的常量
- 5. 內建的類型
- 6. 內建的異常
- 7. String Services
- 8. Data Types
- 9. Numeric and Mathematical Modules
- 10. File and Directory Access
- 11. Data Persistence
- 13. File Formats
- 14. Cryptographic Services
- 15. Generic Operating System Services
- 16. Optional Operating System Services
- 17. Interprocess Communication and Networking
- 18. Internet Data Handling
- 20. Internet Protocols and Support
- 26. Debugging and Profiling
- 28. Python Runtime Services
- Python 2 語言參考
- 1. 簡介
- 2. 詞法分析
- 3. 數據模型
- 4. 執行模型
- 5. 表達式
- 6. 簡單語句
- 7. 復合語句
- 8. 頂層的組件
- 9. 完整的語法規范
- Python 3 教程
- 1. 引言
- 2. Python 解釋器
- 3. Python簡介
- 4. 控制流
- 5. 數據結構
- 6. 模塊
- 7. 輸入和輸出
- 8. 錯誤和異常
- 9. 類
- 10. 標準庫概覽
- 11. 標準庫概覽 — 第II部分
- 12.現在怎么辦?
- 13. 交互式輸入的編輯和歷史記錄
- 14. 浮點數運算:問題和局限