1. 程式人生 > >[python]運算符與表達式

[python]運算符與表達式

位與 兩個 編程模式 參數 匿名函數 通過 part dex {}

1. 數字操作

所有數字類型可進行以下操作:

操作 描述
x + y 加法
x - y 減法
x * y 乘法
x / y 除法
x // y 截斷除法
x ** y 乘方(x的y次方)
x % y 取模(x mod y)
-x 一元減法
+x 一元加法

截斷除法運算符"//",也稱為地板除法,把結果截取為一個整數,並且整數和浮點數均可應用。取模運算符返回的是x // y的余數,對於浮點數,取模運算符返回的是x // y的浮點余數。對於復數,取模和截斷除法運算符是無效的。
以下移位和按位邏輯運算符只能應用於整數:

操作 描述
x << y 左移
x >> y 右移
x & y 按位與
x | y 按位或
x ^ y 按位異或
~x 按位求反

以下內置函數支持所有數字類型:

操作 描述
abs(x) 絕對值
divmod(x,y) 返回(x // y, x % y)
pow(x, y [, modulo]) 返回(x ** y) % module
round(x [,n]) 四舍五入為接近的10^-n的倍數(只返回浮點數)

abs()函數返回數字的絕對值。divmod()函數返回除法操作的商和余數,只對非復數有效。pow()函數可以用於代替**運算符。round()函數將一個浮點數x四舍五入為最近的10^-n的倍數,如果省略n,它將被設為0.

以下比較運算符具有標準的數學解釋,返回值為布爾型的True或False:

操作 描述
x < y 小於
x > y 大於
x == y 等於
x != y 不等於
x >= y 大於等於
x <= y 小於等於

比較運算符可以連在一起,比如x < y < z。這類表達式等價於x < y and y < z。不允許對復數進行比較,否則會引發TypeError異常。只有當操作數屬於同一類型時,對這些操作數進行運算才是有效的。對於內置數字,Python將進行強制類型轉換,轉換規則如下:
1) 如果操作數之一為復數,則將另一個操作數也轉換為復數。

2) 如果操作數之一為浮點數,則將另一個操作數也轉換為浮點數。
3) 否則,兩個操作數必須同時為整數,不需要進行轉換。

2. 序列操作

序列類型(包括字符串、列表和元組)支持的運算符如下所示:

操作 描述
s + r 連接
s n, n s 制作s的n個副本,n為整數
v1, v2..., vn = s 變量解包
s[i] 索引
s[i:j] 切片
s[i:j:stride] 擴展切片
x in s, x not in s 從屬關系
for x in s: 叠代
all(s) 如果s中的所有項都為True,則返回False
any(s) 如果s中的任意項為True,則返回True
len(s) 長度
min(s) s中的最小項
max(s) s中的最大項
sum(s [, initial]) 具有可選初始值的項的和

"+"運算符用於連接相同類型的兩個序列。s * n運算符制作一個序列的n個副本。但是,這些副本僅僅是淺復制。
所有序列都可以被解包為一列變量名稱,例如:

items = [3, 4, 5]
x, y, z = items
datetime = ((5, 19, 2008), (10, 30, "am"))
(month, day, year), (hour, minute, am_pm) = datetime

將值解包到變量中時,變量的個數必須嚴格匹配序列中元素的個數。另外,變量的結構也必須匹配序列的結構。
索引運算符s[n]返回序列中的第n個對象,而s[0]是第一個對象。使用負數索引可以獲取序列尾部的字符。試圖訪問超出邊界的元素將引發IndexError異常。
切片運算符s[i:j]從s中提取一個子序列,它所包含的元素索引k的範圍是i <= k < j。切片運算符支持使用負數索引,並且假定它關聯到序列的結尾。
x in s運算符測試對象x是否在序列s中,返回值為True或False。類似地,x not in s 運算符測試x是否不在序列s中。對於字符串對象,in和not in運算符接受子字符串。比如:" ‘hello‘ in ‘hello world‘ "。需要註意的是,in運算符不支持通配符或任意類別的模式匹配。
for x in s運算符用於叠代序列的所有元素。len(s)返回序列中元素的個數。min(s)和max(s)分別返回一個序列中的最小值和最大值。sum(s)用於對s中的所有項求和,但只在其中的各項代表數字時有效。
字符串和元組是不可變的,創建後不能修改。列表可通過以下運算符進行修改:

操作 描述
s[i] = x 索引賦值
s[i:j] = r 切片賦值
s[i:j:stride] = r 切片擴展賦值
del s[i] 刪除一個元素
del s[i:j] 刪除一個切片
del s[i:j:stride] 刪除一個擴展切片

s[i] = x運算符將列表的元素i修改為引用對象x,同時增加x的引用計數。負索引值將關聯到列表結尾,試圖給超出範圍的索引賦值將引發IndexError異常。切片賦值運算符s[i:j] = r將使用序列r中的元素替換元素k,其中k的範圍是i <= k < j。如果有必要,將對序列s進行擴展或收縮,以便容納r中的所有元素,例如:

a = [1, 2, 3, 4, 5]
a[1] = 6 # a = [1, 6, 3, 4, 5]
a[2:4] = [10, 11] # a = [1, 6, 10, 11, 5]
a[3:4] = [-1, -2, -3] # a = [1, 6, 10, -1, -2, -3, 5]
a[2:] = [0] # a = [1, 6, 0]

切片賦值可以提供一個可選的步進參數。但這種行為受到的限制更大,右邊的參數必須與要替換切片的元素個數完全相同。
del s[i]運算符從列表中刪除元素i,同時減少它的引用計數。del s[i:j]刪除切片內的所有元素。切片刪除也可以指定步進參數。
使用運算符<、>、<=、>=、==、!=可以對序列進行比較。比較兩個序列時,首先比較每個序列的第一個元素。如果它們不同,即可以得出結論。如果它們相同,就繼續比較。如果a是b的子序列,那麽a < b。

3. 字符串格式化

取模運算符(s % d)生成格式化的字符串,其中s是一個格式字符串,而d是一個對象元組或映射對象(字典)。格式字符串包含兩類對象:普通字符和轉換說明符,將使用可表示相關元組或映射中元素的格式化字符串來替換這些轉換說明符。如果d是一個元組,轉換說明符的個數必須與d中對象的個數保持一致。如果d是一個映射,每個轉換說明符都必須與映射中的一個有效鍵名關聯。每個轉換說明符都以%開始,如下表:

字符 輸出格式
d, i 十進制整數或長整數
u 無符號整數或長整數
o 八進制整數或長整數
x 十六進制整數或長整數
X 十六進制整數(大寫字母)
f 浮點數,如[-]m.dddddd
e 浮點數,如[-]m.dddddd+(-)xx
E 浮點數,如[-]m.dddddd+(-)xx
g, G 指數小於-4或更高精度時使用%e或%E,否則使用%f
s 字符串或任意對象
r 同repr()生成的字符串
c 單個字符
% 字面量%

在%字符和轉換字符之間,可以出現以下修飾符,並且只能按照以下順序出現:
1) 位於括號中的一個鍵名,用於從映射對象中選出一個具體項。
2) -,左對齊標誌。默認是右對齊。
3) +,表示應該包含數字符號。
4) 0,表示一個零填充。
5) 一個指定最小自動寬度的數字。
6) 一個小數點,用於按照精度分割字段寬度。
7) 一個數字,指定要打印字符串中的最大字符個數,浮點數中小數點之後的位數,或者整數的最小位數。
星號"*"字符用於在任意寬度的字段中替換數字。
以下代碼給出一些例子:

a = 42
b = 13.142783
c = "hello"
d = {‘x‘:13, ‘y‘:1.54321, ‘z‘: ‘world‘}
e = 5628398123741234

r = "a is %d" % a # r = "a is 42"
r = "%10d %f" % (a, b) # r = "        42  13.142783"
r = "%+010d %E" % (a, b) # r = "+0000000042 1.314278E+01"
r = "%(x)-10d %(y)0.3g" % d # r = "13        1.54"
r = "%0.4s %s" % (c, d[‘z‘]) # r = "hell world"
r = "%*.*f" % (5, 3, b) # r = "13.143"
r = "e = %d" % e # r = "e = 5628398123741234"

字符串格式化有一種更加高級的形式,即使用字符串的s.format(args, kwargs)方法。該方法收集位置參數和關鍵字參數的任意集合,並使用它們的值來替換s中嵌入的占位符。例如:

r = "{0} {1} {2}".format{‘GOOG‘, 100, 490.91}
r = "{name} {shares} {price}".format{name=‘GOOG‘, shares=100, price=490.10}

如果要輸出一個"{"或"}",必須使用"{{"或"}}"的形式。使用占位符還可以執行其他索引和屬性查找,例如:

stock = {
    ‘name‘: ‘GOOG‘,
    ‘shares‘: 100,
    ‘price‘: 490.91
}
r = "{0[name]} {0[shares]} {0[price]}".format(stock)

這些擴展中只允許使用名稱,而不支持任意的表達式、方法調用和其他操作。另外,還可以指定格式說明符。方法是用一個冒號":"給每個占位符添加可選的格式說明符,例如:

r = "{name:8} {shares:8d} {price:8.2f}".format(name=‘GOOG‘, shares=100, price=490.10)

說明符的一般格式是[fill[align]][sign][0][width][.pricision][type],[ ]中的每個部分都是可選的。width說明符指定要使用的最小字段寬度,align說明符的值可取"<"、">"或"^"之一,分別代表在字段中左對齊、右對齊和居中對齊。fill是一個可選的填充字符,用於填充空白。type說明符表示數據的類型。格式說明符的sign部分是"+"、"-"或空格" "之一,表示符號。說明符的precision部分用於為十進制數提供精度位置。

4. 字典和集合操作

字典提供名稱和對象之間的映射,它支持的操作如下:

操作 描述
x = d[k] 通過鍵進行索引
d[k] = x 通過鍵進行賦值
del d[k] 通過鍵刪除一項
k in d 測試某個鍵是否存在
len(d) 字典中的項數

鍵的值可以是任意不可變對象,如字符串、數字和元組。另外,字典的鍵也可以是一列用逗號分開的值,例如:

d = {}
d[1, 2, 3] = "foo"
d[1, 0, 3] = "bar"
# 等價於
d[(1, 2, 3)] = "foo"
d[(1, 0, 3)] = "bar"

set和frozenset類型支持大量常見的集合操作,如下所示:

操作 描述
s | t s和t的並集
s & t s和t的交集
s - t 求差集
s ^ t 求對稱差集
len(s) 集合中項數
max(s) 最大值
min(s) 最小值

並集、交集和差集操作的結果與最左邊的操作數具有相同類型。例如,如果s是一個frozenset,而t是一個set,那麽結果的類型將是frozenset。

5. 增量賦值

Python提供的增量賦值運算符如下所示:

操作 描述
x += y x = x + y
x -= y x = x - y
x *= y x = x * y
x /= y x = x / y
x //= y x = x // y
x **= y x = x ** y
x %= y x = x % y
x &= y x = x & y
x |= y x = x | y
x ^= y x = x ^ y
x >>= y x = x >> y
x <<= y x = x << y

增量賦值不會違反可變性或者原地修改對象。因此,執行代碼 x += y時,將創建一個值為x + y的全新對象x。

6. 屬性和函數調用運算符

點"."運算符用於訪問對象的屬性,例如

foo.x = 3
print(foo.y)
a = foo.bar(3, 4, 5)

表達式中可以出現多個點運算符,如foo.y.a.b。點運算符還可以用於函數的中間結果,如a = foo.bar(3, 4, 5).spam。
f(args)運算符用於調用f上的函數。函數的每個參數都是一個表達式。在調用函數前,將從左到右對所有參數表達式進行求值,這有時稱為應用序求值。使用functools模塊中的partial()函數可以對函數參數進行部分求值,例如:

def foo(x, y, z):
    return x + y + z
from functools import partial
f = partial(foo, 1, 2) # 為foo的參數x和y提供值
f(3) # 調用foo(1, 2, 3)

partial()函數對一個函數的某些參數求值,返回一個稍後可以調用的對象,以提供余下的參數。函數參數的部分求值與叫做科裏化的過程關系十分緊密。所謂科裏化的機制是:把一個帶有多個參數的函數分解為一系列函數,其中每個函數帶有其中一個參數。

7. 轉換函數

有時必須在內置類型之間執行轉換,只需用類型名稱作為函數。另外,還有幾個內置函數可用於執行特殊類別的轉換。所有這些函數均返回一個新對象,該對象代表了轉換後的值。

函數 描述
int(x [, base]) 將x轉換為一個整數。如果x是一個字符串,base用於指定基數
float(x) 將x轉換為一個浮點數
Complex(real [, imag]) 創建一個復數
str(x) 將對象x轉換為字符串表示
repr(x) 將對象x轉換為一個表達式字符串
format(x [, format_spec]) 將對象x轉換為格式化的字符串
eval(str) 對字符串求值並返回對象
tuple(s) 將s轉換為元組
list(s) 將s轉換為列表
set(s) 將s轉換為集合
dict(s) 創建字典。d必須是(key, value)元組的序列
frozenset(s) 將s轉換為不可變集合
chr(x) 將整數轉換為字符串
ord(x) 將字符轉換為其整數值
hex(x) 將整數轉換為十六進制字符串
bin(x) 將整數轉換為二進制字符串
oct(x) 將整數轉換為八進制字符串

需要註意的是,str()和reprt()函數返回的結果可能不同。repr()函數通常會創建一個表達式字符串,可以使用eval()對它求值以重新創建對象。ord()函數返回一個字符的整數順序值。在Unicode中,這個值就是一個整數代碼點。chr()函數用於將整數轉換成字符。在創建容器的函數中,如list()、tuple()、set()等,參數可以是支持叠代的任意對象,而叠代生成的所有項將用於填充要創建的對象。

8. 布爾表達式與真值

and、or和not關鍵字構成了布爾表達式。這些運算符的行為如下所示:

運算符 描述
x or y 如果x為false,則返回y;否則返回x
x and y 如果x為false,則返回x;否則返回y
not x 如果x為false,則返回1;否則返回0

使用表達式來判斷True或False值時,True、任意非零數字、非空字符串、列表、元組或字典都將返回True,而False、零、None和空的列表、元組和字典都將返回False。布爾表達式從左至右求值,而且只有需要時才會計算右邊的操作數。

9. 對象的比較與身份

等於運算符(x == y)可以測試x和y的值是否相等。對於列表和元組,只有其中的所有元素都相等,它們才相等。而對於字典,只有當x和y的鍵都相同,而且鍵相同的所有對象的值都相等才會返回True。兩個集合相等的條件是用==運算符進行比較時,它們具有相同的元素。
身份運算符(x is y和x is not y)可以測試兩個對象是否引用了內存中的同一個對象。一般而言,x == y,但x is not y。
比較操作也可以在兩個非兼容對象之間進行,如一個文件和一個浮點數,但返回結果是任意的,可能沒有意義。另外也可能導致異常。

10. 運算優先級

Python運算符的操作順序如下表:

運算符 名稱
(...), [...], {...} 創建元組、列表和字典
s[i], s[i:j] 索引和切片
s.attr 屬性
f(...) 函數調用
+x, -x, ~x 一元運算符
x ** y 乘方(從右至左運算)
x * y, x / y, x // y, x % y 乘法、除法、地板除法、取模
x + y, x - y 加法、減法
x << y, x >> y 移位
x & y 按位與
x ^ y 按位異或
x | y 按位或
x < y, x <= y 比較、身份和序列成員檢查
x > y, x >= y
x == y, x != y
x is y, x is not y
x in s, x not in s
not x 邏輯非
x and y 邏輯與
x or y 邏輯或
lambda args: expr 匿名函數

運算順序並非由上表的x和y的類型決定。因此,即便是用戶自定義對象,也可以重新定義每個運算符。

11. 條件表達式

常見的編程模式是根據表達式的結果,有條件地進行賦值,例如:

if a <= b:
    minvalue = a
else:
    minvalue = b

使用條件表達式可以簡化這段代碼,例如:

minvalue = a if a <= b else b

在這類表達式中,首先求值的是中間的條件。如果結果為True,再對if語句左面的表達式求值,否則就會對else後面的表達式求值。

[python]運算符與表達式