跳转到内容

Python 编程/运算符

来自 Wikibooks,开放世界中的开放书籍


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

链接

模运算

[编辑 | 编辑源代码]

模运算(两个操作数除法的余数,而不是商)可以使用 % 运算符找到,或者使用 divmod 内置函数找到。divmod 函数返回一个包含商和余数的元组

>>> 10 % 7
3
>>> -10 % 7
4

请注意,-10 % 7 等于 +4,而在 C 语言中它等于 -3。这是因为 Python 向负无穷大取整而不是零。因此,余数向正无穷大增加。因此,由于 -10 / 7 = -1.4286 被向下取整为 -2.0,所以余数变为 x,使得 -14 + x = -10。

链接

与某些其他语言不同,变量可以直接取反

>>> x = 5
>>> -x
-5

比较运算

[编辑 | 编辑源代码]
运算符 含义
< 小于
> 大于
<= 小于等于
>= 大于等于
== 等于
!= 不等于

数字、字符串和其他类型可以比较相等/不相等和排序

>>> 2 == 3
False
>>> 3 == 3
True
>>> 3 == '3'
False
>>> 2 < 3
True
>>> "a" < "aa"
True

身份运算

[编辑 | 编辑源代码]

运算符 isis 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

链接

增强赋值

[编辑 | 编辑源代码]

有一种简写方法可以将操作的结果赋值给其中一个输入

>>> 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

与 (and)

[编辑 | 编辑源代码]

与运算符只有在所有布尔值都为真时才返回真。如果任何一个为假,则与运算符返回假。

if a and b:
    do_this
else:
    do_this

非 (not)

[编辑 | 编辑源代码]

非运算符只作用于一个布尔值,并简单地返回其相反值。因此,真变为假,假变为真。

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 的链接中显示。

链接

参考文献

[编辑 | 编辑源代码]
[编辑 | 编辑源代码]
华夏公益教科书