Python 编程/运算符
Python 数学运算按预期工作
>>> x = 2
>>> y = 3
>>> z = 5
>>> x * y
6
>>> x + y
5
>>> y - x
1
>>> x * y + z
11
>>> (x + y) * z
25
>>> 3.0 / 2.0 # True division
1.5
>>> 3 // 2 # Floor division
1
>>> 2 ** 3 # Exponentiation
8
请注意,Python 遵循运算符优先级。
Python 内置了幂运算符 **,它可以作用于整数、浮点数或复数。它在运算符优先级中占据其适当的位置。
>>> 2**8
256
在 Python 3.x 中,斜杠运算符 ("/") 对所有类型(包括整数)执行真除,因此,例如 3/2==1.5
[1][2]。即使两个输入都是整数,结果也是浮点类型:4 / 2 的结果是 2.0。
在 Python 3.x 和最新的 2.x 中,整数参数和浮点数参数的地板除是通过使用双斜杠 ("//") 运算符实现的。对于负结果,这与 C 语言中的整数除法不同,因为在 Python 中 -3 // 2 == -2,而在 C 中 -3 / 2 == -1:C 将负结果舍入到零,而 Python 舍入到负无穷大。
请注意,由于浮点数运算的限制,舍入误差可能导致意外结果。例如
>>> print(0.6/0.2) 3.0 >>> print(0.6//0.2) 2.0
对于 Python 2.x,使用斜杠运算符 ("/") 对两个整数或长整数进行除法时,使用地板除(在除法后应用向下取整函数),并产生一个整数或长整数。因此,5 / 2 == 2 且 -3 / 2 == -2。以这种方式使用 "/" 进行除法已弃用;如果您想要地板除,请使用 "//"(在 Python 2.2 及更高版本中可用)。除以或除以浮点数将导致 Python 使用真除。因此,为了确保在 Python 2.x 中进行真除:x=3; y=2; float(x)/y == 1.5
。
链接
- 6.7. 二元算术运算,在 Python 语言参考,docs.python.org
- Python 风格的整数除法和模运算在 C 中,stackoverflow.com
- C++ 中负数的整数除法舍入,stackoverflow.com
- 在 Python 中,在整数除法中向零舍入的良好方法是什么?,stackoverflow.com
- 为什么 Python 的整数除法向下取整,python-history.blogspot.com
模运算(两个操作数除法的余数,而不是商)可以使用 % 运算符找到,或者使用 divmod 内置函数找到。divmod 函数返回一个包含商和余数的元组。
>>> 10 % 7
3
>>> -10 % 7
4
请注意,-10 % 7 等于 +4,而在 C 语言中它等于 -3。这是因为 Python 向负无穷大取整而不是零。因此,余数向正无穷大增加。因此,由于 -10 / 7 = -1.4286 被向下取整为 -2.0,所以余数变为 x,使得 -14 + x = -10。
链接
- 6.7. 二元算术运算,在 Python 语言参考,docs.python.org
与某些其他语言不同,变量可以直接取反
>>> x = 5
>>> -x
-5
运算符 | 含义 |
---|---|
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
== | 等于 |
!= | 不等于 |
数字、字符串和其他类型可以比较相等/不相等和排序
>>> 2 == 3
False
>>> 3 == 3
True
>>> 3 == '3'
False
>>> 2 < 3
True
>>> "a" < "aa"
True
运算符 is
和 is not
用于测试对象身份,并与 ==(等于)形成对比:x is y
当且仅当 x 和 y 是内存中同一个对象的引用时才为真。x is not y
产生相反的真值。请注意,身份测试比相等测试更严格,因为两个不同的对象可能具有相同的值。
>>> [1,2,3] == [1,2,3]
True
>>> [1,2,3] is [1,2,3]
False
对于内置的不可变数据类型(如 int、str 和 tuple),Python 使用缓存机制来提高性能,即解释器可能会决定重用现有的不可变对象,而不是生成一个具有相同值的新的对象。对象缓存的细节在不同的 Python 版本之间可能会发生变化,并且不保证是系统无关的,因此对不可变对象的标识检查,例如 'hello' is 'hello'
、(1,2,3) is (1,2,3)
、4 is 2**2
在不同的机器上可能产生不同的结果。
在某些 Python 实现中,以下结果适用
print(8 is 8) # True
print("str" is "str") # True
print((1, 2) is (1, 2)) # False - whyever, it is immutable
print([1, 2] is [1, 2]) # False
print(id(8) == id(8)) # True
int1 = 8
print(int1 is 8) # True
oldid = id(int1)
int1 += 2
print(id(int1) == oldid)# False
链接
- 3. 数据模型,python.org
- 2. 内置函数 # id,python.org
- 5. 表达式 # is,python.org
有一种简写方法可以将操作的结果赋值给其中一个输入
>>> x = 2
>>> x # 2
2
>>> x *= 3
>>> x # 2 * 3
6
>>> x += 4
>>> x # 2 * 3 + 4
10
>>> x /= 5
>>> x # (2 * 3 + 4) / 5
2
>>> x **= 2
>>> x # ((2 * 3 + 4) / 5) ** 2
4
>>> x %= 3
>>> x # ((2 * 3 + 4) / 5) ** 2 % 3
1
>>> x = 'repeat this '
>>> x # repeat this
repeat this
>>> x *= 3 # fill with x repeated three times
>>> x
repeat this repeat this repeat this
逻辑运算符是作用于布尔值的运算符。
或运算符如果任何一个布尔值为真则返回真。如果它们都不为真(换句话说,它们都为假),则或运算符返回假。
if a or b:
do_this
else:
do_this
与运算符只有在所有布尔值都为真时才返回真。如果任何一个为假,则与运算符返回假。
if a and b:
do_this
else:
do_this
非运算符只作用于一个布尔值,并简单地返回其相反值。因此,真变为假,假变为真。
if not a:
do_this
else:
do_this
这里的运算符优先级是:非优先,与其次,或最后。特别是,“True or True and False or False”变为“True or False or False”,结果为 True。
警告,逻辑运算符可以作用于布尔值以外的事物。例如,“1 and 6”将返回 6。具体来说,“and”返回第一个被认为是假的的值,或者如果所有值都被认为是真则返回最后一个值。“or”返回第一个真值,或者如果所有值都被认为是假则返回最后一个值。在 Python 中,数字 零 和空字符串、列表、集合等被认为是假。您可以使用 bool()
检查 Python 中某物是否被认为是真或假。例如,bool(0.0)
和 bool([])
都返回 False
。
Python 中用于位运算的运算符与 C 语言中的类似。它们包括 &(按位与)、|(按位或)、^(异或)、<<(左移)、>>(右移)和 ~(取反)。位运算的增强赋值运算符(也称为复合赋值运算符)包括 &=、|=、^=、<<= 和 >>=。位运算符适用于整数,包括负数和非常大的整数;对于移位运算符,第二个操作数必须是非负数。在 Python 内部帮助中,这在 EXPRESSIONS 和 BITWISE 主题下有介绍。
示例
- 0b1101 & 0b111 == 0b101
- 注意:0b 开头表示二进制字面量,就像 0x 开头表示十六进制字面量一样。
- 0b1 | 0b100 == 0b101
- 0b111 ^ 0b101 == 0b10
- 1 << 4 == 16
- 7 >> 1 == 3
- 1 << 100 == 0x10000000000000000000000000
- 支持较大的结果。
- 1 << -1
- 错误:第二个操作数必须是非负数。
- -2 & 15 == 14
- 对于位运算,负整数被视为使用补码表示,并在前面有无限个 1。因此,-2 就如同 0x...FFFFFFFFFE,将其与 15 (0xF) 进行按位与运算,结果为 0xE,即 14。
- format(-2 % (1 << 32), "032b")
- 确定一个字符串,显示 -2 的隐式补码表示的最后 32 位。
- ~-2 == 1
- 上述关于负整数处理的说明适用。对于取反 (~),这种处理方式得到 ~x == -1 * (x + 1)。可以验证:min((~x == -1 * (x + 1) for x in range(-10 ** 6, 10 ** 6))) == True。
- ~1 == -2
- 上面提到的公式 ~x == -1 * (x + 1) 适用。在按位取反的解释中,1 的所有虚假前导零都被翻转为前导一,然后被解释为 -2 的补码表示,就如同 0x...FFFFFFFFFE。
- x = 0b11110101; x &= ~(0xF << 1); x == 0b11100001
- 一个常见的习惯用法是使用取反来清除最低有效位 5 到 2,这显示了负数的无限前导一的补码隐式表示在位运算中的实用性。适用于任意大的 x。
- ~2 & 0xFFFFFFFF == 0xFFFFFFFD
- 我们可以通过将取反的结果与最大无符号 32 位整数 0xFFFFFFFF 进行按位与运算,来模拟 32 位整数的按位取反。对于 8 位取反、16 位取反等,我们可以通过将取反的结果与 0xFF、0xFFFF 等进行按位与运算来进行类似的操作。
- 2 ^ 0xFFFFFFFF == 0xFFFFFFFD
- 模拟固定大小的按位取反的另一种方法是,与该大小的所有 F 进行异或运算。
- v = 2.0 & 2
- 产生错误:没有自动将浮点数转换为整数,也没有对浮点数的底层表示进行运算。
- int.bit_length(0x8000) == 16
- 确定表示该整数所需的位数。因此,min((int.bit_length(1 << x) == x + 1 for x in range(100000))) == True。
增强赋值运算符的示例
- a = 0b1101; a &= 0b111; a == 0b101
- a = 0b1; a |= 0b100; a == 0b101
- a = 0b111; a ^= 0b101; a == 0b10
- a = 1; a <<= 4; a == 16
- a = 7; a >>= 1; a == 3
类定义可以重载类的实例的运算符;因此,例如,集合重载了管道 (|) 运算符,表示集合并集:{1,2} | {3,4} == {1,2,3,4}。重载方法的名称为 __and__ 用于 &、__or__ 用于 |、__xor__ 用于 ^、__invert__ 用于 ~、__lshift__ 用于 <<、__rshift__ 用于 >>、__iand__ 用于 &=、__ior__ 用于 |=、__ixor__ 用于 ^=、__ilshift__ 用于 <<= 和 __irshift__ 用于 >>=。
位运算的应用示例包括 CRC 和 MD5 的计算。诚然,为了获得最大的速度,这些通常会在 C 而不是 Python 中实现;实际上,Python 有用 C 编写的这些库。尽管如此,在 Python 中实现也是可能的,并在下面指向 Rosetta Code 的链接中显示。
链接
- 位运算符,wiki.python.org
- 位操作,wiki.python.org
- 整数类型的位运算 在库参考中,docs.python.org
- 2.5. 运算符 在 Python 语言参考中,docs.python.org
- 6. 表达式 在 Python 语言参考中,docs.python.org
- 3. 数据模型 在 Python 语言参考中,docs.python.org
- "整数 (int) [...] 为了移位和掩码操作的目的,假设使用二进制表示,负数使用 2 的补码的变体表示,这使得看起来好像有一个无限的符号位字符串向左延伸。"
- 按位运算,wikipedia.org
- C 语言中的按位运算,wikipedia.org
- PEP 203 – 增强赋值,python.org
- 按位运算及其用法,stackoverflow.com
- CRC-32 # Python,rosettacode.org
- MD5/实现 # Python,rosettacode.org
- longobject.c 在 python/cpython 中,github.com - 函数 long_bitwise、long_rshift、long_lshift 和 long_invert