本章描述了 Python 中表達(dá)式的組成元素的含義。
句法注意:在本章和之后的章節(jié)中,描述句法時使用與詞法分析時不同的擴(kuò)展 BNF 記法。當(dāng)某個句法規(guī)則(可能是可選的)具有如下形式:
name ::= othername
并且未給出特定語義時,name 的這種形式的意義就與 othername 相同。
當(dāng)用以下短語“數(shù)值型參數(shù)轉(zhuǎn)換為通用類型”描述數(shù)值型操作數(shù)時,參數(shù)使用第三章結(jié)尾處的強(qiáng)制規(guī)則進(jìn)行強(qiáng)制轉(zhuǎn)換。如果兩個參數(shù)都屬于標(biāo)準(zhǔn)數(shù)值型,就使用以下的強(qiáng)制規(guī)則:
對于某些運(yùn)算符有特殊的規(guī)則(例如,作為運(yùn)算符‘%’左側(cè)參數(shù)的字符)。擴(kuò)展必須制定轉(zhuǎn)換規(guī)則。
原子是表達(dá)式最基本的組成單位,最簡單的原子是標(biāo)識符或者字面值。 以圓括號、方括號或大括號括住的符號在句法上也看成是原子。原子的句法如下:
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display | generator_expression | yield_atom
作為一個原子出現(xiàn)的標(biāo)識符是一個名字。參看標(biāo)識符和關(guān)鍵字以及命名空間和結(jié)構(gòu)框架。
當(dāng)某名字捆綁的是一個對象時,使用該原子就是使用那個對象。當(dāng)某名字沒有捆綁就直接使用它,則會拋出一個 NameError 異常。
私有名字變換: 在類定義中, 以兩個或多個下劃線開始,并且尾部不是以兩個或多個下劃線結(jié)束的標(biāo)識符,它被看作是類的私有名字。在產(chǎn)生它的代碼之前, 私有名字被變換成更長的形式。這種變換是在將去掉前導(dǎo)下劃線的類名插入到名字前,再在類名前插入一個下劃線。例如,在類 Ham 中定義的標(biāo)識符 _ _spam,會被變換成 _ _Ham_spam。本變換是不依賴于使用該標(biāo)識符處代碼的句法上的上下文的。如果變換后的結(jié)果過長(超過 255 個字符), 就會執(zhí)行該P(yáng)ython實現(xiàn)定義的截短名字的操作。如果某類的名字僅僅由下劃線組成,這種變換是不會發(fā)生的。
Python 支持字符串、字節(jié)和各種數(shù)值型的字面值:
literal ::= stringliteral | bytesliteral | integer | floatnumber | imagnumber
使用一個字面值會得到一個具有給定值的相應(yīng)類型的對象(字符串、字節(jié)、整數(shù)、浮點數(shù)、復(fù)數(shù)),如果是浮點數(shù)和復(fù)數(shù),那么這個值可能是個近似值,詳見 Literals。
所有字面值都屬于不可變的數(shù)據(jù)類型,因此對象的標(biāo)識比起它們的值來說顯得次要一些。多次使用相同值的字面值(在程序代碼中以相同形式出現(xiàn)或者以不同的形式出現(xiàn))可能獲得的是相同的對象或具有相同值的不同對象?!?
一個括號表達(dá)式是位于一對小括號內(nèi)可選的表達(dá)式表。
parenth_form ::= "(" [expression_list] ")"
表達(dá)式表生成什么類型的值括號表達(dá)式也就生成什么類型的值:如果表達(dá)式表中包括了至少一個逗號,它就生成一個元組;否則,就生成那個組成表達(dá)式表的唯一的表達(dá)式。
一個空的表達(dá)式表會生成一個空的元組對象。因為元組是不可變的,因此這里適用字符串所用的規(guī)則(即兩個具有空表達(dá)式的元組可能是同一個對象也可能是不同的對象)。
請注意元組不是依靠小括號成定義的,而是使用逗號。其中空元組是個例外,此時要求有小括號——在表達(dá)式中允許沒有小括號的“空”可能會引起歧義,并容易造成難以查覺的筆誤。
為了構(gòu)建一個列表、一個集合或者一個字典,Python 提供了一種特殊的語法叫“表示”,每一個都有兩種方式:
推導(dǎo)式的一般語法元素是:
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]
推導(dǎo)式是由至少一個 for 子句以及后跟零個或多個 for 或 if 子句構(gòu)成的一個表達(dá)式組成,在這種情況下,新列表的元素由每個 for 或 if 子句決定,嵌套是從左至右方向的,而且每執(zhí)行到最內(nèi)部的語句塊就產(chǎn)生一個列表元素。
請注意,推導(dǎo)式是在一個單獨的范圍內(nèi)執(zhí)行的,所以目標(biāo)列表的名字分配不能泄漏到封閉的范圍內(nèi)。
一個列表用一對方括號括住的表達(dá)式序列(可能為空)表示:
list_display ::= "[" [expression_list | comprehension] "]"
使用一個列表會生成一個新的列表對。它的值由表達(dá)式表或由推導(dǎo)式給出。當(dāng)給出一個逗號分隔的表達(dá)式表時,從左到右地對每個元素求值然后按順序放進(jìn)列表對象中。 如果給出的是推導(dǎo)式, 列表是由從推導(dǎo)式得出的元素組合而成。
一個集合是用花括號來表示的,它和字典的區(qū)別是缺少分隔鍵和值的冒號。
set_display ::= "{" (expression_list | comprehension) "}"
集合的表示將產(chǎn)生一個新的集合對象,內(nèi)容是由一個表達(dá)式序列或者一個推導(dǎo)式來制定。當(dāng)提供一個由逗號分隔的表達(dá)式列表時,將從左到由計算它的元素并把它們加入到集合對象中。當(dāng)提供一個推導(dǎo)式時,集合將由從推導(dǎo)式中得出的元素組成。
一個空的集合不能由{ }構(gòu)建,這種形式將構(gòu)建一個空的字典。
一個字典用一對大括號括住的鍵/數(shù)據(jù)對的序列(可能為空)表示:
dict_display ::= "{" [key_datum_list | dict_comprehension] "}"
key_datum_list ::= key_datum ("," key_datum)* [","]
key_datum ::= expression ":" expression
dict_comprehension ::= expression ":" expression comp_for
使用一個字典會生成一個新的字典對象。
鍵/數(shù)據(jù)對按在字典中定義的從左到右的順序求值:每個鍵對象作為鍵嵌入到字典中存儲相應(yīng)的數(shù)據(jù)。這意味著你可以在鍵/數(shù)據(jù)列表中多次指定相同的鍵,鍵值是最后一次指定的值。
字典推導(dǎo)式,與列表和集合推導(dǎo)式相反,需要兩個由冒號分開的表達(dá)式,并且其后跟一般的 “for” 和 “if” 子句。當(dāng)推導(dǎo)式在運(yùn)行時,產(chǎn)生的鍵和值元素將按照它們生成的順序插入到新的字典中去。
關(guān)于鍵值類型的限制已在前述章節(jié) 標(biāo)準(zhǔn)類型層次 提及(總而言之,鍵的類型應(yīng)該是可散列的,這就排除了所有的可變對象)。重復(fù)鍵之間的沖突不會被檢測到;對給定的(有重復(fù)的)鍵來說,最后出現(xiàn)的數(shù)據(jù)(就是文字顯示中出現(xiàn)在最右邊的)成為(最終的)勝利者。
生成器表達(dá)式是由圓括號括起來的緊湊的生成器符號。
generator_expression ::= "(" expression comp_for ")"
一個生成器表達(dá)式產(chǎn)生一個新的生成器對象。它是被括在圓括號中而不是方括號或者花括號中,除此之外,它的語法和推導(dǎo)式一樣。
當(dāng) __next__() 方法被生成器對象調(diào)用時,在生成器表達(dá)式中用到的變量將被計算(和普通生成器相同)。然而,最左邊的 for 子句將被立即計算,這樣由它產(chǎn)生的錯誤將在處理生成器代碼中其它可能出現(xiàn)的錯誤之前被發(fā)現(xiàn)。隨后的 for 子句將不會被立即計算,因為它們將取決于之前的 for 循環(huán)。例如 (x*y for x in range(10) for y in bar(x))。
當(dāng)調(diào)用生成器表達(dá)式時,圓括號可以被忽略,只保留一個參數(shù)。詳情請參見調(diào)用章節(jié)。
yield_atom ::= "("yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
yield 表達(dá)式只有在定義一個生成器功能時才會被使用,所以只能被用在函數(shù)定義的過程中。在函數(shù)體內(nèi)使用 yield 表達(dá)式將會使該函數(shù)變成一個生成器。
當(dāng)一個生成器函數(shù)被調(diào)用時,它將返回一個被稱為生成器的迭代器。該生成器將控制生成器函數(shù)的執(zhí)行。當(dāng)生成器的某個方法被調(diào)用時,生成器函數(shù)將開始執(zhí)行。同時,在執(zhí)行第一個 yield 表達(dá)式的過程中,即上次被掛起的地方,將返回表達(dá)式列表的值給生成器調(diào)用程序。所謂掛起,即所有的本地狀態(tài)都將被保留,包括局部變量的綁定情況、指令指針、內(nèi)部計算堆棧以及一些異常處理的狀態(tài)。當(dāng)調(diào)用生成器的某種方法,該執(zhí)行過程恢復(fù)時,該函數(shù)可以像 yield 表達(dá)式是另外一個外部表達(dá)式調(diào)用一樣運(yùn)行?;謴?fù)執(zhí)行后 yeild 表達(dá)式的值將取決于使該執(zhí)行過程恢復(fù)的方法。如果使用 __next__() 函數(shù)(通常是通過 for 語句或者內(nèi)部 next() 函數(shù)),則結(jié)果為 None。如果使用 send() 函數(shù),結(jié)果為傳遞到該方法中的值。
所有這些特性讓生成器函數(shù)和協(xié)同程序非常像,它們可以多次輸出,有多于一個的程序執(zhí)行入口點,而且它們的執(zhí)行過程可以被掛起。唯一的區(qū)別是當(dāng)輸出一次執(zhí)行結(jié)果后,需要繼續(xù)執(zhí)行時,生成器函數(shù)無法控制,只有當(dāng)生成器被調(diào)用時才可以被控制。
在 try 塊中的任何地方都可以使用 yield 表達(dá)式。如果一個生成器在它結(jié)束(引用計數(shù)達(dá)到0或者被垃圾收集)之前沒有被恢復(fù),迭代器的 close() 方法將會被調(diào)用,允許各種 finally 語句執(zhí)行。
當(dāng)使用 yield from <expr> 時,認(rèn)為表達(dá)式為從迭代器。所有由該從迭代器提供的值將直接返回給當(dāng)前生成器方法的調(diào)用程序。如果有合適的方法,所有由 send() 函數(shù)傳遞的值和所有由 throw() 函數(shù)傳遞的異常都將傳送給底層的迭代器。如果找不到合適的方法,send() 函數(shù)將拋出AttributeError或者 TypeError異常,但是 throw() 函數(shù)只拋出傳遞異常。
當(dāng)?shù)讓盈B加器完成計算時,拋出的 StopIteration 異常實例的值屬性將變成 yield 表達(dá)式的值。它可以在拋出異常 StopIteration 異常時明確的設(shè)置,或者當(dāng)子迭代器是一個生成器時(通過子生成器返回值)自動生成。
3.3版本修改的地方:添加 yield from <expr> 語句使子生成器具備控制功能。
當(dāng) yield 表達(dá)式是賦值表達(dá)式右邊唯一的表達(dá)式時,圓括號可以被忽略。
可參見:
PEP 0255 – 簡單生成器
提議在 Python 中 添加生成器和 yield 的說明.
PEP 0342 – 通過高級生成器實現(xiàn)的協(xié)同程序
提議增強(qiáng)生成器的 API 和語法,讓它們和簡單生成器一樣便于使用。
PEP 0380 – 子生成器的授權(quán)語法
提議介紹 yield-from 語法,讓授權(quán)子生成器變得容易。
這一部分將描述生成器迭代器的方法,該方法可以控制生成器程序的執(zhí)行。
請注意:當(dāng)生成器已經(jīng)開始運(yùn)行的時候,調(diào)用以下任何一個方法將拋出 ValueError 異常。
generator.__next__()
開啟生成器函數(shù)的執(zhí)行或者在上次執(zhí)行 yield 表達(dá)式的地方恢復(fù)執(zhí)行。當(dāng)一個生成器函數(shù)被 next() 方法恢復(fù)執(zhí)行,最近的 yield 表達(dá)式通常計算為 None。當(dāng)生成器再次被掛起,表達(dá)式列表的值被返回給 next() 函數(shù)的調(diào)用者,執(zhí)行過程將繼續(xù)到下一個 yield 表達(dá)式。如果生成器沒有生成另外一個值就直接退出執(zhí)行,將引發(fā)一個 StopIteration 異常。
該方法通常被間接調(diào)用,如通過一個 for 循環(huán)或者通過內(nèi)建 next() 函數(shù)。
generator.send(value)
恢復(fù)執(zhí)行過程并且傳遞給生成器函數(shù)一個值。value 參數(shù)的值將被賦予當(dāng)前 yield 表達(dá)式。send() 方法返回生成器生成的下一個值。如果生成器沒有產(chǎn)生其它值并退出執(zhí)行后,將引發(fā) StopIteration 異常。當(dāng)調(diào)用 send() 函數(shù)啟動生成器時,必須以 None 作為參數(shù),因為沒有接收該值得 yield 表達(dá)式。
generator.throw(type[, value[, traceback]])
當(dāng)生成器被暫停將拋出一個 type 類型的異常,并返回由生成器函數(shù)生成的 next 值。如果生成器沒有返回其它值并退出執(zhí)行,將拋出一個 StopIteration 異常。如果生成器函數(shù)沒有對傳入的異常進(jìn)行捕獲處理時,異常將返回給調(diào)用者。
generator.close()
當(dāng)生成器函數(shù)被暫停執(zhí)行時將拋出 GeneratorExit 異常(正常退出或者已被關(guān)閉)。如果生成器函數(shù)拋出一個 StopIteration (正常退出或者已被關(guān)閉)或者 GeneratorExit 異常時(不捕獲處理異常),生成器將正常結(jié)束。如果生成器返回其它值,將拋出 RuntimeError 異常。如果生成器拋出其它類型的異常,則異常將直接被返回給調(diào)用者。如果生成器因為異常或者正常退出而結(jié)束運(yùn)行,則 close() 函數(shù)不起任何作用。
此處用一個簡單的例子來說明生成器和生成器函數(shù)的執(zhí)行。
>>> def echo(value=None):
... print("Execution starts when 'next()' is called for the first time.")
... try:
... while True:
... try:
... value = (yield value)
... except Exception as e:
... value = e
... finally:
... print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.
使用 yield from 語句的例子,請參見PEP380:委托至子生成器的語法。
基元指和語言本身中接合最緊密的若干操作。它們的語法如下:
primary ::= atom | attributeref | subscription | slicing | call
一個屬性引用是由一個主元(primary)后跟一個句號和一個名字構(gòu)成:
attributeref ::= primary "." identifier
主元必須是一個支持屬性引用的類型的對象。引用對象屬性時,即要求該被對象生成指定名字的屬性?!≡撨^程可以通過重寫 _ getattr _() 方法具體化?!?如果該屬性無效,將會拋出異常 AttribError。否則,對象決定生成的屬性的類型和值。對同一屬性的引用多次求值是有可能生成不同對象的。
一個下標(biāo)選擇一個有序類型對象(字符串,元祖或列表)或映射(字典)對象的一項:
subscription ::= primary "[" expression_list "]"
主元(primary)必須是一個支持下標(biāo)計算的對象(例如列表或字典)。用戶自定義的對象通過定義 __getitem__() 方法來支持下標(biāo)。
如果主元是一個映射,則對表達(dá)式表求值的結(jié)果必須是映射中的一個鍵,然后此下標(biāo)操作在主元映射中選擇與該鍵所對應(yīng)的值。(如果表達(dá)式表只有一項,那么它就是一個元組)。
如果主元是一個有序類型,表達(dá)式(列表)的計算結(jié)果應(yīng)該是一個整數(shù)或片段(見下方討論部分)。
正式的語法對序列中的負(fù)索引沒有特別的規(guī)定;但是,所有內(nèi)建序列都提供了一個 __getitem__() 方法來解決負(fù)索引,即如果索引值是負(fù)數(shù), 就加上該序列的長度(例如, x[-1] 選擇 x 的最后一項)。
字符串的元素是字符,字符不是單獨的數(shù)據(jù)類型而僅僅是只有一個字符長的字符串。
一個片斷選擇某個有序類型對象(如字符串、元組、列表)一段范圍之內(nèi)的項。片斷可以作為表達(dá)式使用,或者是賦值和 del 語句的目標(biāo)。 下面是片斷的句法:
slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
在這里形式句法的說明中有點含糊: 任何看起來像表達(dá)式表的語法構(gòu)件也能看作是片斷表,所以任何下標(biāo)都可以解釋為片斷。但這樣要比更復(fù)雜的句法要合適,該定義是沒有歧義的,在這種情況下(在片斷表中沒有包括適當(dāng)?shù)钠瑪嗷蛘呤÷詫懛ǎ﹥?yōu)先將其解釋為下標(biāo),而不是片斷。
一個片斷的語義如下:主要是由該片斷表構(gòu)成的鍵作索引(使用相同的 __getitem__() 方法作為正常下標(biāo))。如果一個片斷表包括至少一個逗號,那么鍵就是一個包括由片斷中的所有項轉(zhuǎn)換而來的元組; 否則, 就用獨立的片斷項作轉(zhuǎn)換成為鍵。為表達(dá)式的片斷項轉(zhuǎn)換后仍是該表達(dá)式。正常的片斷轉(zhuǎn)換后是一個 start,stop 和step 屬性為給定的下限,上限和步長的片斷對象(見3.2節(jié)),對于缺少的表達(dá)式用 None 替代。
一個調(diào)用就是以一系列參數(shù)(可能為空)調(diào)用一個可調(diào)用對象(例如,函數(shù)):
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," keyword_arguments]
[","*" expression] ["," keyword_arguments]
["," "**" expression]
| [keyword_arguments]() ["," "*" expression]
["," keyword_arguments] ["," "**" expression]
| "*" expression ["," keyword_arguments]
["," "**" expression]
| "**" expression
positional_arguments ::= expression ("," expression)
keyword_arguments ::= keyword_item ("," keyword_item)
keyword_item ::= identifier "=" expression
在關(guān)鍵字參數(shù)表后面可以出現(xiàn)一個逗號,但它在語義上是沒有任何作用的。
首先的工作是導(dǎo)出一個可調(diào)用對象(用戶自定義函數(shù),內(nèi)建函數(shù),內(nèi)建方法對象,類定義,類實例方法,包含方法 __call__() 的對象都是可調(diào)用的)。所有的參數(shù)表達(dá)都在試圖調(diào)用之前被計算。關(guān)于形參列表的句法請參考章節(jié)函數(shù)定義。
如果給出了關(guān)鍵字參數(shù),它們首先被轉(zhuǎn)換為位置參數(shù)。具體如下:第一步,根據(jù)形參表創(chuàng)建一串空閑槽,如果有N個位置參數(shù),它們就被放在前N個槽中。然后,對于每個關(guān)鍵字參數(shù),它的標(biāo)識符用于檢測其對應(yīng)的槽(如果其標(biāo)識符與第一個形參數(shù)名相同,它就占用第一個槽,以此類推)如果發(fā)現(xiàn)某個槽已經(jīng)被占用,則引發(fā) TypeError異常。否則將參數(shù)的值(即使為 None )放進(jìn)槽中。當(dāng)所有關(guān)鍵字參數(shù)處理完成后, 所有未填充的槽用在函數(shù)定義中的相應(yīng)的默認(rèn)值填充。(默認(rèn)值是由函數(shù)定義時計算出來的,所以,像列表和字典這樣的可變類型對象作默認(rèn)值時,它們會被那些沒有相應(yīng)槽指定參數(shù)值的調(diào)用所共享,通常要避免這樣做)。如果仍有未填充默認(rèn)的槽位,就會引發(fā)一個 TypeError 異常。否則,所有被填充的槽當(dāng)作調(diào)用的參數(shù)表。
CPython實現(xiàn)細(xì)節(jié):CPython實現(xiàn)了一種位置參數(shù)沒有名字的內(nèi)建函數(shù),即使位置參數(shù)被命名也是為了閱讀方便,因此無法提供關(guān)鍵詞。在實現(xiàn),這是實現(xiàn)在 C 使用 PyArg_ParseTuple() 解析他們的論點的情況下。
如果位置參數(shù)的個數(shù)比形參槽數(shù)多,并且在未使用 *identifier 句法的情況下,會引發(fā) TypeError 異常。使用該種句法時,形參接受一個包括有額外位置參數(shù)的元組(如果沒有額外和位置參數(shù),它就為空)。
如果任何一個關(guān)鍵字參數(shù)與形參名不匹配,并且在未使用 **identifier句法的情況下,會引發(fā) TypeError 異常。使用該種句法時,形參接受一個包括有額外關(guān)鍵字參數(shù)的字典(關(guān)鍵字作為鍵,參數(shù)值作為該鍵對應(yīng)的值),字典如果沒有額外和關(guān)鍵字參數(shù),它就為空。
如果在函數(shù)調(diào)用中使用了 *exprsiones 句法, 那么 exprsiones的結(jié)果必須是有序類型的。這個有序類型對象的元素被當(dāng)作附加的位置參數(shù)處理; 如果存在有位置參數(shù) x1,...,xN,并且 *exprsiones 的計算結(jié)果為 y1,...,yM,那么它與具有 M+N 個參數(shù) x1,...xN,y1,...,yM 的調(diào)用等效。
由此可以得到一個推論: 盡管 *exprsiones 句法出現(xiàn)在任何關(guān)鍵字參數(shù)之后,但它在處理關(guān)鍵字參數(shù)之前計算。(如果有的話,**exprsiones 也是如此,參見下述),所以:
>>> 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
一同使用關(guān)鍵字語法和 *expression 的情況十分罕見,所以實際上這種混亂是不會發(fā)生的。
如果在函數(shù)調(diào)用中使用 **expression 句法,expression 計算結(jié)果必須是一個字典(的子類)。其內(nèi)容作為附加的關(guān)鍵字參數(shù)。如果一個關(guān)鍵字出現(xiàn)在 expression 中并且是一個顯式關(guān)鍵字參數(shù),就會引發(fā) TypeError 異常。
使用 *identifier” 或 **identifier 句法的形參不能作為位置參數(shù)或關(guān)鍵字參數(shù)名使用。
一個元組如果沒有引發(fā)異常,通常會返回一些值,可能為 None。怎樣計算這個值依賴于可調(diào)用對象的類型。
如果它是—
用戶自定義函數(shù):
執(zhí)行此函數(shù)的代碼塊,并把參數(shù)傳給它。它要做的第一件事就是將形參與實參對應(yīng)起來。關(guān)于這點參見函數(shù)定義 當(dāng)代碼塊執(zhí)行到 return 語句時,會指定這次函數(shù)調(diào)用的返回值。
內(nèi)建函數(shù)或內(nèi)建方法:
結(jié)果依賴于解釋器,詳見 Built-in Functions。
類對象:
返回該類的一個新實例。
類實例的方法:
調(diào)用對應(yīng)的用戶自定義函數(shù),其參數(shù)個數(shù)比普通的函數(shù)調(diào)用多一:該實例成為方法的第一個參數(shù)。
類實例:
類實例必須定義方法 call ();效果與調(diào)用該方法相同。
冪運(yùn)算符比在操作數(shù)左邊的一元運(yùn)算符有更高的優(yōu)先級;但比右面的一元運(yùn)算符要低。句法為:
power ::=primary ["**" u_expr]
因此,在一串沒有括號的由冪運(yùn)算符和一元運(yùn)算符組成的序列,會從左到右面求值(沒有強(qiáng)制改變求值順 序):-1**2 結(jié)果為 -1。
當(dāng)以兩個參數(shù)調(diào)用 pow() 時,冪運(yùn)算符與內(nèi)建函數(shù) pow() 有相同的語義: 生成左邊參數(shù)的右邊參數(shù)次方。數(shù)值型參數(shù)首先轉(zhuǎn)換成通用類型。結(jié)果類型是參數(shù)經(jīng)強(qiáng)制規(guī)則轉(zhuǎn)換后的結(jié)果。
對于整數(shù)操作數(shù),其結(jié)果的類型與操作數(shù)相同除非第二個參數(shù)為負(fù)數(shù);在這種情況下,所有的參數(shù)被轉(zhuǎn)換為 float 進(jìn)而結(jié)果也是 float。例如,10\*\*2 返回 100,但 10\*\*-2 返回 0.01。
0.0的任意負(fù)數(shù)指冪會引發(fā) ZeroDivisionError 異常。一個負(fù)數(shù)的分?jǐn)?shù)指冪結(jié)果是一個 complex。(早期的版本中會引發(fā) ValueError 異常。)
所有一元算術(shù)運(yùn)算符(和位運(yùn)算符)有相同的優(yōu)先級:
u_expr ::=power | "-" u_expr | "+" u_expr | "~" u_expr
一元運(yùn)算符-(減)對其數(shù)值型操作數(shù)取負(fù)。
一元運(yùn)算符+(加)不改變其數(shù)值型操作數(shù)。
一元運(yùn)算符 (取反)對其普通整數(shù)或長整數(shù)參數(shù)求逆(比特級)。x的比特級求逆運(yùn)算定義為 -(x+1)。它僅僅用于整數(shù)型的操作數(shù)。
在以上所有的三種情況下,如果參數(shù)的類型不合法,就會引發(fā)一個 TypeError 異常。
二元算術(shù)運(yùn)算符的優(yōu)先級符合我們的正常習(xí)慣。注意其中有些運(yùn)算符也可以應(yīng)用于非數(shù)值型操作數(shù)。除了冪運(yùn)算符,它們只分兩個優(yōu)先級:一個是乘法類運(yùn)算,一個是加法類運(yùn)算。
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" [u_expr]() | m_expr "/" u_expr | m_expr "%" 上一篇:介紹下一篇:執(zhí)行模型