操作符和标点符号
操作符和一些符号(个)
1
2
3
4
5
6
7
8
9
| + & += &= == != ( )
- | -= |= < <= [ ]
* ~ *= ^= -> > >= { }
/ ^ /= <<= = , ;
// << //= >>= ... . :
% >> %=
** **=
@ @=
:=
|
算术操作符(8个)
注意
Python没有像Go、JavaScript那样提供++
、--
。若是需要自增1,可使用v += 1
;若是需要自减1,可使用v += 1
。
1 +
加法。
左结合性。
1
2
3
4
5
6
7
| print(1 + 2) # 3
print(1 + 2.0) # 3.0
print(1.0 + 2.0) # 3.0
print(1 + 2 + 3) # 6
print((1 + 2) + 3) # 6
print(0.1+0.1) # 0.2
print(0.1+0.2) # 0.30000000000000004
|
注意
该符号,也可以用作连接字符串。
2 -
减法。
左结合性。
1
2
3
4
5
6
7
8
9
10
11
12
| print(2 - 1) # 1
print(2 - 1.0) # 1.0
print(2.0 - 1) # 1.0
print(2.0 - 1.0) # 1.0
print(3 - 2 - 1) # 0
print((3 - 2) - 1) # 0
print(3 - (2 - 1)) # 1
print(3.1 - 2 - 1) # 0.10000000000000009
print(3 - 2.1 - 1) # -0.10000000000000009
print(3 - 2 - 1.1) # -0.10000000000000009
|
3 *
乘法。
左结合性。
注意
该符号,也可以用作重复操作符。
1
2
3
4
5
6
7
8
9
10
11
| print(2 * 3) # 6
print(2 * 3) # 6.0
print(2.0 * 3) # 6.0
print(2.0 * 3.0) # 6.0
print(2.0 * 3 * 4) # 24.0
print(2 * 3.0 * 4) # 24.0
print(2 * 3 * 4.0) # 24.0
print(2 * 3 * 4) # 24
print((2 * 3) * 4) # 24
|
4 /
除法。
左结合性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| print(10 / 3) # 3.3333333333333335
print(10 / -3) # -3.3333333333333335
print(-10 / 3) # -3.3333333333333335
print(-10 / -3) # 3.3333333333333335
print(10 / 3.0) # 3.3333333333333335
print(10 / -3.0) # -3.3333333333333335
print(-10 / 3.0) # -3.3333333333333335
print(-10 / -3.0) # 3.3333333333333335
print(10.1 / 1) # 10.1
print(10.1 / -1) # -10.1
print(10.1 / 1.0) # 10.1
print(10.1 / -1.0) # -10.1
print(-10.1 / 1.0) # -10.1
print(-10.1 / -1.0) # 10.1
print(10.9 / 1) # 10.9
print(10.9 / -1) # -10.9
print(10.9 / 1.0) # 10.9
print(10.9 / -1.0) # -10.9
print(-10.9 / 1.0) # -10.9
print(-10.9 / -1.0) # 10.9
print(100 / 2 / 2) # 25
print((100 / 2) / 2) # 25
print(100 / (2 / 2)) # 100
|
5 //
整除。向负无穷取整。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| print(10 // 3) # 3
print(10 // -3) # -4
print(-10 // 3) # -4
print(-10 // -3) # 3
print(10 // 3.0) # 3.0
print(10 // -3.0) # -4.0
print(-10 // 3.0) # -4.0
print(-10 // -3.0) # 3.0
print(10.1 // 1) # 10.0
print(10.1 // -1) # -11.0
print(10.1 // 1.0) # 10.0
print(10.1 // -1.0) # -11.0
print(-10.1 // 1.0) # -11.0
print(-10.1 // -1.0) # 10.0
print(10.9 // 1) # 10.0
print(10.9 // -1) # -10.0
print(10.9 // 1.0) # 10.0
print(10.9 // -1.0) # -11.0
print(-10.9 // 1.0) # -11.0
print(-10.9 // -1.0) # 10.0
|
6 %
取余。向负无穷取数。结果的符号跟随除数
。
左结合性。
取余运算的公式为:
1
| a % b = a − (a // b) ∗ b
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| print(10 % 3) # 1
print(10 % -3) # -2
print(10 % 3.0) # 1.0, 1.0 = 10 - (10 // 3.0) * 3.0
print(10 % -3.0) # -2.0, -2.0 = 10 - (10 // -3.0) * (-3.0)
print(10.1 % 3) # 1.0999999999999996
print(10.1 % -3) # -1.9000000000000004
print(10.1 % 3.0) # 1.0999999999999996
print(10.1 % -3.0) # -1.9000000000000004
print(-10.1 % 3) # 1.0999999999999996
print(-10.1 % -3) # -1.0999999999999996
print(-10.1 % 3.0) # 1.9000000000000004
print(-10.1 % -3.0) # -1.0999999999999996
print(10.9 % 3) # 1.9000000000000004
print(10.9 % -3) # -1.0999999999999996
print(10.9 % 3.0) # 1.9000000000000004
print(10.9 % -3.0) # -1.0999999999999996
print(-10.9 % 3) # 1.0999999999999996
print(-10.9 % -3) # -1.9000000000000004
print(-10.9 % 3.0) # 1.0999999999999996
print(-10.9 % -3.0) # -1.9000000000000004
|
7 **
乘方、幂运算。
右结合性。
1
2
3
4
| print(2**3.0) # 8.0
print(2.0**3.0) # 8.0
print(2**3**4) # 2417851639229258349412352
print(2**(3**4)) # 2417851639229258349412352
|
8 @
矩阵乘法。
左结合性。
注意
它是在 Python 3.5 中引入的,专门为线性代数和科学计算设计的。
1
2
3
4
5
6
7
8
9
10
11
| import numpy as np
# 创建3个矩阵
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = np.array([[9, 10], [11, 12]])
# 使用 @ 进行矩阵乘法
print(a @ b) # [[19 22] [43 50]]
print(a @ b @ c) # [[ 413 454] [ 937 1030]]
print(a @ (b @ c)) # [[ 413 454] [ 937 1030]]
|
位操作符(6个)
1 &
按位与。
左结合性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| x = 3
y = 7
z = 8
print(f"{x:#010b}->{x}\n{y:#010b}->{y}")
# 0b00000011->3
# 0b00000111->7
x1 = x & y
print(f"{x1:#010b}->{x1}\n")
# 0b00000011->3
print(f"{x:#010b}->{x}\n{z:#010b}->{z}")
# 0b00000011->3
# 0b00001000->8
x2 = x & z
print(f"{x2:#010b}->{x2}\n")
# 0b00000000->0
|
提示
:#010b
是格式化说明符,其中:
#
表示保留 0b
前缀。0
表示用0来填充空白位置。10
表示整个输出的宽度为 10 个字符(包括 0b
前缀)。b
表示二进制格式。
除了以上:#010b
的方式指定打印的格式外,还可以使用bin()
内置函数,用来打印整型数字的二进制形式。其效果不如使用:#010b
来得直接。
x = 3
y = 7
print(f"{bin(x):10}->{x}\n{bin(y):10}->{y}")
# 0b11->3
# 0b111->7
x1 = x & y
print(f"{bin(x1)}->{x1}\n")
# 0b11->3
2 |
按位或。
左结合性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| x = 3
y = 7
z = 8
print(f"{x:#010b}->{x}\n{y:#010b}->{y}")
# 0b00000011->3
# 0b00000111->7
x1 = x | y
print(f"{x1:#010b}->{x1}\n")
# 0b00000111->7
print(f"{x:#010b}->{x}\n{z:#010b}->{z}")
# 0b00000011->3
# 0b00001000->8
x2 = x | z
print(f"{x2:#010b}->{x2}\n")
# 0b00001011->11
|
3 ^
按位异或。
左结合性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| x = 3
y = 7
z = 8
print(f"{x:#010b}->{x}\n{y:#010b}->{y}")
# 0b00000011->3
# 0b00000111->7
x1 = x ^ y
print(f"{x1:#010b}->{x1}\n")
# 0b00000100->4
print(f"{x:#010b}->{x}\n{z:#010b}->{z}")
# 0b00000011->3
# 0b00001000->8
x2 = x ^ z
print(f"{x2:#010b}->{x2}\n")
# 0b00001011->11
|
4 ~
按位取反。返回其对应的补码表示的结果
左结合性。
5 <<
二进制左移位。移动到左边的位被丢弃,右边的位置则用零填充。
左结合性。
左移操作符实际上是将数字乘以 2 的幂次方。
注意
<<
,只能用于整数类型的数据。否则,报TypeError
类型的错误。
1
2
| 2.0 << 1
TypeError: unsupported operand type(s) for <<: 'float' and 'int'
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| x = 3
print(f"{x:#010b}->{x}\n") # 0b00000011->3
x = x << 1
print(f"{x:#010b}->{x}\n") # 0b00000110->6
x = x << 1
print(f"{x:#010b}->{x}\n") # 0b00001100->12
y = -3
print(f"{y:#010b}->{y}\n") # -0b0000011->-3
y = y << 1
print(f"{y:#010b}->{y}\n") #-0b0000110->-6
y = y << 1
print(f"{y:#010b}->{y}\n") #-0b0001100->-12
|
6 >>
二进制右移位。移动过程中,移出右边的位会被丢弃,左边的新位置会根据符号位填充。
左结合性。
右移操作符实际上是将数字除以 2 的幂次方。
注意
>>
,只能用于整数类型的数据。否则,报TypeError
类型的错误。
1
2
| 2.0 >> 1
TypeError: unsupported operand type(s) for >>: 'float' and 'int'
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| x = 256
print(f"{x:#010b}->{x}\n") # 0b100000000->256
x = x >> 1
print(f"{x:#010b}->{x}\n") # 0b10000000->128
x = x >> 1
print(f"{x:#010b}->{x}\n") # 0b01000000->64
y = -256
print(f"{y:#010b}->{y}\n") # -0b100000000->-256
print(f"{y:#011b}->{y}\n") # -0b100000000->-256
print(f"{y:#012b}->{y}\n") # -0b100000000->-256
print(f"{y:#013b}->{y}\n") # -0b0100000000->-256
y = y >> 1
print(f"{y:#010b}->{y}\n") # -0b10000000->-128
print(f"{y:#011b}->{y}\n") # -0b10000000->-128
print(f"{y:#012b}->{y}\n") # -0b010000000->-128
y = y >> 1
print(f"{y:#010b}->{y}\n") # -0b1000000->-64
print(f"{y:#011b}->{y}\n") # -0b01000000->-64
print(f"{y:#012b}->{y}\n") # -0b001000000->-64
|
从:#010b
、:#011b
、:#012b
、:#013b
可以看出:
- 输出的位宽包括了符号位;
- 输出的位宽不足时,会自动满足所显示数值的需要,如示例中所示:当
y=-256
,此时,:#010b
、:#011b
显然不足以显示全部位,但输出的结果却也能完全显示-256
的二进制表示形式;
赋值操作符(15个)
1
2
| += -= *= /= //= %= **= @= :=
&= |= ^= <<= >>=
|
1 =
赋值。
左结合性。
2 +=
相加后赋值给第一个操作数。
左结合性。
3 -=
相减后赋值给第一个操作数。
左结合性。
4 *=
相乘后赋值给第一个操作数。
左结合性。
5 /=
相除后赋值给第一个操作数。
左结合性。
6 //=
整除后赋值给第一个操作数。向负无穷取整。
左结合性。
7 %=
取余后赋值给第一个操作数。
左结合性。
8 **=
幂运算后赋值给第一个操作数。
右结合性
。
9 @=
矩阵乘法后赋值给第一个操作数。
左结合性。
它是在 Python 3.5 中引入的,专门为线性代数和科学计算设计的。
1
2
3
4
5
6
7
8
9
10
| import numpy as np
# 创建两个矩阵
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 使用 @= 进行矩阵乘法后赋值
a @= b
print(a) # [[19 22] [43 50]]
|
10 :=
左结合性。
也称为“海象操作符”(Walrus Operator)。它是在 Python 3.8 中引入的,允许在表达式中进行赋值操作,可以减少代码中的冗余,使代码更加简洁、易读。
没有:=
之前的代码:
1
2
3
| a = 7
if a > 6:
print(f"It has a value of {a} and satisfies the condition perfectly.")
|
有了:=
之后的代码:
if (a := 7) > 6:
print(f"It has a value of {a} and satisfies the condition perfectly.")
确实代码变简洁了!
11 &=
按位进行与操作
后赋值给第一个操作数。
左结合性。
12 |=
按位进行或操作
后赋值给第一个操作数。
左结合性。
13 ^=
按位进行异或操作
后赋值给第一个操作数。
左结合性。
14 <<=
按位左移后赋值给第一个操作数。
左结合性。
15 >>=
按位右移后赋值给第一个操作数。
左结合性。
逻辑操作符(3个)
1 and
逻辑与
左结合性。
1
2
3
4
| x = 2
y = 3
if x > 1 and y > 2:
print(f"You can found {x}>1 and {y}>2.")
|
2 or
逻辑或
左结合性。
1
2
3
4
| x = 2
y = 3
if x > 1 or y > 2:
print(f"You can found {x}>1 or {y}>2.")
|
3 not
逻辑非。
右结合性。
1
2
3
| x = 2
if not(x < 1):
print(f"You can found {x}>=1.")
|
关系操作符(9个)
1 ==
比较整型数值类型,没有问题:
1
2
3
4
| print(1 == 1) # True
print(1 == 2) # False
print(123456789012345678901234567890123456789012345678901234567890123456789 == 123456789012345678901234567890123456789012345678901234567890123456789) # True
|
比较浮点型数值类型,存在问题:
1
2
3
4
5
6
7
8
| print(0.1 == 0.1) # True
print(0.1 + 0.2 == 0.3) # False
# 可以通过math.isclose函数来解决
print(math.isclose(0.1 + 0.2, 0.3)) # True
print(math.isclose(0.1 + 0.2, 0.3,rel_tol=1e-15)) # True
print(math.isclose(0.1 + 0.2, 0.3,rel_tol=1e-16)) # False
print(math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-100)) # False
|
比较字符串,布尔值,列表、元组、字典、集合、自定义对象(若自定义对象没有实现了__eq__
方法,则比较两个对象的 id 是否相等(即两个对象指向的内存地址是否是一致的))。
1
2
3
4
5
6
| print("" == "a") # False
print(True == False) # False
print([1, 2, 3] == [1, 2, 4]) # False
print((1,) == (1,2)) # False
print({"Name":"zlx"} == {"Name":"zlongx"}) # False
print({1,"a",(1, 2, 3)} == {1,"b",(1, 2, 3)}) # False
|
自定义对象没有定义__eq__
方法:
1
2
3
4
5
6
7
8
9
10
| class Person:
def __init__(self, name):
self.name = name
person1 = Person("Alice")
person2 = Person("Alice")
person3 = Person("Bob")
print(person1 == person2) # False
print(person1 == person3) # False
|
自定义对象有定义__eq__
方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Person:
def __init__(self, name):
self.name = name
def __eq__(self, other):
if not isinstance(other, Person):
return NotImplemented
return self.name == other.name
person1 = Person("Alice")
person2 = Person("Alice")
person3 = Person("Bob")
print(person1 == person2) # True
print(person1 == person3) # False
|
2 !=
比较整型数值类型,没有问题:
1
2
3
4
| print(1 != 1) # False
print(1 != 2) # True
print(123456789012345678901234567890123456789012345678901234567890123456780 != 123456789012345678901234567890123456789012345678901234567890123456789) # True
|
比较浮点型数值类型,存在问题:
1
2
3
4
5
6
7
8
| print(0.1 != 0.1) # False
print(0.1 + 0.2 != 0.3) # True
# 可以通过math.isclose函数来解决
print(math.isclose(0.1 + 0.2, 0.3)) # True
print(math.isclose(0.1 + 0.2, 0.3,rel_tol=1e-15)) # True
print(math.isclose(0.1 + 0.2, 0.3,rel_tol=1e-16)) # False
print(math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-100)) # False
|
比较字符串,布尔值,列表、元组、字典、集合、自定义对象(如果自定义对象没有实现 __ne__
方法,那么 !=
操作符会比较对象的标识,而不是值。)。
1
2
3
4
5
6
| print("" != "a") # True
print(True != False) # True
print([1, 2, 3] != [1, 2, 4]) # True
print((1,) != (1,2)) # True
print({"Name":"zlx"} != {"Name":"zlongx"}) # True
print({1,"a",(1, 2, 3)} != {1,"b",(1, 2, 3)}) # True
|
自定义对象没有定义__ne__
方法:
1
2
3
4
5
6
7
8
9
10
| class Person:
def __init__(self, name):
self.name = name
person1 = Person("Alice")
person2 = Person("Alice")
person3 = Person("Bob")
print(person1 != person2) # True
print(person1 != person3) # True
|
自定义对象有定义__ne__
方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Person:
def __init__(self, name):
self.name = name
def __eq__(self, other):
if not isinstance(other, Person):
return NotImplemented
return self.name == other.name
person1 = Person("Alice")
person2 = Person("Alice")
person3 = Person("Bob")
print(person1 != person2) # False
print(person1 != person3) # True
|
3 <
比较整数、浮点数(存在问题)、字符串。
1
2
3
4
5
| print(1 > 2) # False
print(0.1 + 0.2 > 0.3) # True
print("ab" > "abc") # False
print("你好" > "您好") # False
print("您好" > "你好") # True
|
4 <=
5 >
6 >=
7 is
8 is not
9 in
10 not in
1
2
3
4
5
6
7
8
9
|
is(身份比较)判断两个对象是否引用同一个对象。
不是用来比较对象的值是否相等,而是比较对象在内存中的位置是否相同。
is not(身份比较)判断两个对象是否引用同一个对象。
不是用来比较对象的值是否相等,而是比较对象在内存中的位置是否不相同。
in(成员测试)判断某个元素是否存在于某个容器
(如列表、元组、字符串、集合、字典)中,如果元素在容器中,则返回 True
not in(成员测试)判断某个元素是否不存在于某个容器
(如列表、元组、字符串、集合、字典)中,如果元素不在容器中,则返回 True
|
指针操作符(0个)
在 Python 中,没有像 C 或 C++ 那样的显式指针操作符。Python 是一种高级编程语言,它对内存管理进行了抽象,开发者无需直接操作内存地址,也没有显式的指针操作符(如 *
和 &
)。
为什么 Python 没有指针?
- 内存管理:Python 通过自动内存管理机制(例如垃圾回收)来管理对象的生命周期和内存分配,因此开发者不需要直接操作内存或使用指针。
- 对象引用:Python 使用引用语义。当你赋值或传递一个对象时,实际上是在传递对象的引用,而不是对象的副本。这种引用类似于指针的概念,但更为高级,开发者不需要关心引用的内存地址。
Python 中的对象引用
虽然 Python 没有显式的指针操作符,但每个对象实际上都是通过引用来操作的。因此,你可以认为变量名是指向对象的“引用”,而不是对象本身。多个变量可以指向同一个对象。
示例:
1
2
3
4
5
| a = [1, 2, 3]
b = a # b 是对 a 的引用,不是副本
b.append(4)
print(a) # 输出: [1, 2, 3, 4]
|
在这个例子中,a
和 b
都指向同一个列表对象,所以通过 b
修改列表的内容会影响到 a
。
id()
函数
虽然没有指针操作符,但 Python 提供了 id()
函数来获取对象的内存地址。它返回一个唯一标识符,这个标识符通常是对象在内存中的地址。
1
2
| x = 10
print(id(x)) # 打印 x 对象在内存中的地址
|
ctypes
模块
如果确实需要进行低级别的内存操作,Python 提供了 ctypes
模块。ctypes
允许你调用 C 函数和处理指针等底层操作,但这在 Python 中很少用到,通常只在特定的性能要求或与 C 代码交互时使用。
其他操作符(11个)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| ( 左括号
) 右括号
[ 左方括号
] 右方括号
{
}
.
, 逗号分隔符
1.多变量赋值
2.创建元组分隔多个值
3.分隔多个函数形参/实参
4.在构造列表、字典和集合时,逗号用于分隔元素或键值对。
5.解构赋值
6.引入多个模块
7.生成器表达式和列表推导式中用于分隔多个变量
; 分号
: 冒号 1.定义定义代码块,用于定义语句块的开始,例如在条件判断、循环、函数定义、类定义等语句中使用。
2.用于切片操作,允许我们从序列类型(如列表、元组、字符串)中提取子序列。
3.在字典中,冒号用于将键和值分隔开,定义键值对。
4.函数参数的类型注解,在 Python 3 中,冒号也可以用于函数参数的类型注解,指示参数的类型。
-> 函数返回值的类型注解,在 Python 3 中,->也可以用于函数返回值的类型注解,指示返回值的类型
|
说明,
用于创建元组
1
2
| my_tuple = 1, 2, 3 # 等价于 (1, 2, 3)
single_element_tuple = 1, # 创建包含一个元素的元组,需要逗号
|
1
2
| my_tuple = (1, 2, 3)
single_element_tuple = (1,)
|
说明,
用于解构赋值
1
2
3
4
5
| my_tuple = (10, 20, 30)
a, b, c = my_tuple
print(a) # 10
print(b) # 20
print(c) # 30
|
操作符优先级
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
| 优先级从高到低排列:
(1)用于强制改变操作符的默认优先级。
() 圆括号
(2)索引、切片、函数调用、属性访问(左结合性)
[] 获取指定索引的列表、字符串、元组(注意不包括集合)
[:] 切片
() 函数调用
. 属性访问
(3)一元操作符(右结合性)
+ 正号
- 负号
not 逻辑非
~ 按位取反
(4)幂运算 (右结合)
** 示例:print(2*2**2**3) // 512 等价于 print(2*(2**(2**3)))
(5)乘法、除法、取余、取整(左结合性)
* 乘法
/ 除法
// 整除
% 取余
(6)加法和减法(左结合性)
+ 加法
- 减法
(7)位操作符(左结合性)
<< 左移
>> 右移
& 按位与
^ 按位异或
| 按位或
(3)
|(按位或)
^(按位异或)
(4)关系操作符
==(等于)
!=(不等于)
<(小于)
<=(小于等于)
>(大于)
>=(大于等于)
(5)逻辑运算符
and(逻辑与)
or(逻辑或)
(6)赋值运算符(右结合性)
=(赋值)
+=(加后赋值)
-=(减后赋值)
*=(乘后赋值)
/=(除后赋值)
//(整除后赋值)
%=(取余后赋值)
**=(取幂后赋值)
<<=(左移后赋值)
>>=(右移后赋值)
&=(按位与后赋值)
|=(按位或后赋值)
^=(按位异或后赋值)
(7)其他运算符(左结合性)
,(逗号)
|
操作符的结合行
参见以上优先级部分。