2.关于数字2, 我们要去聊聊那个叫做运算符与表达式的概念。
它是一种面向对象的编程语言, 在这里面任何存在的东西都被看作是对象。一个具体的对象包含了数据这一部分和行为那一部分, 而它的行为主要是通过方法这个手段给体现出来的。人们可以通过去重写某些特殊的方法这种方式, 从而来实现运算符重载这件事。
运算符本身也是表现对象行为的一种表现形式。不同类别的对象它们所支持的运算符存在着差异。即便是同一种运算符当它作用于不同类的对象时也可能展示出不一样的行为特点。这种情形正是所谓的“多态”概念的体现所在。
在计算机编程领域, 单个的常量或者是变量,通常被视为最为简单的一类表现形式, 同时, 那些借助了各种不同类型的运算符号以及函数调用来进行组合连接起来的式子, 同样也归属于表现形式的范围。
对于大家所熟知的算术方面的运算符号、关系判断类的运算符号、逻辑推理类型的运算符号以及位操作相关的运算符号等常见类型之外, 系统还额外支持一些具有特殊性质的运算符号, 这些特殊的符号例如包含了成员资格测试类运算符、集合相关的运算符号以及针对同一性进行测试的类别标志等。
在使用这个过程的时候, 我们需要去注意一个事情, 就是很多那个运算符它们是具有多种不同的含义的, 然后在作用在不同对象的时候, 它的那些含义并不完全是一样的, 所以说这个东西是非常灵活的, 比较常用的那些运算符的情况, 你可以参考表2-3。
在运算符优先级的规则当中, 算术运算符所占的地位是最高的, 排在其次的是位运算符, 接着是成员测试运算符, 然后再是关系运算符, 后面还有逻辑运算符等等, 至于算术运算符, 它会按照先乘法和除法、后加法和减法这个基本的运算原则来执行计算, 虽然说是存在着一套非常严格的关于运算符优先级的规则体系, 可是在编写比较复杂的那种表达式的时候, 咱们还是被非常强烈地建议要去使用小圆圈括起来的括号把这个里面的逻辑清晰地标注和说明出来, 这么做的目的就是为了提升整个代码容易阅读的程度。
你要知道, 圆括号是一种可以用来明确并且改变表达式运算顺序的非常有力的工具。
你如果在合适的位置去使用圆括号的话, 那么就会让表达式的含义变得更为清晰和明确起来。
2.2.1 算术运算符
算术运算符这个东西, 它包括了加法这个操作符号是加号, 减法这个操作符号是减号, 乘法这个操作符号是星号, 除法这个操作符号是斜杠, 整除这个操作符号是两个斜杠, 求余这个操作符号是百分号, 还有幂运算这个操作符号是两个星号。
加法运算符是"+", 除了进行算术上的加法计算之外, 还适用于列表、元组以及字符串这类对象的连接操作, 但是它不支持将不同类型的对象放在一起相加或者连接在一起。
# 连接两个列表
print([1, 2, 3] + [4, 5, 6]) # 输出: [1, 2, 3, 4, 5, 6]
# 连接两个字符串
print('abcd' + '1234') # 输出: 'abcd1234'
# True 会被看作 1
print(True + 3) # 输出: 4
乘法这个符号也就是那个星号, 除了用来做算术里的乘法计算以外, 还可以用在列表这种类型、元组这种类型、字符串这种类型, 这几个都属于序列的类型, 然后和一个整数去做乘法, 这个意思就是指把序列里面的元素重复一遍, 最后生成一个新的序列对象。
# 列表重复
print([1, 2, 3] * 3) # 输出: [1, 2, 3, 1, 2, 3, 1, 2, 3]
# 字符串重复
print('abc' * 3) # 输出: 'abcabcabc'
对于除法那个符号是正斜线, 还有整除这个双正斜线的符号。
print(3 / 2) # 输出: 1.5 (真除法)
print(15 // 4) # 输出: 3 (整除)
求余运算符是用百分号来表示的, 它这种符号可以拿来给整数做求余数的运算, 也可以拿来给实数做求余数的运算, 同时还可以拿它来做字符串格式化使用。
print(7 % 3) # 输出: 1
print(123.45 % 3.2) # 输出: 1.849999999999996
在计算过程中, 那个用来表示做幂乘这种运算的符号是双星号, 也就是大家常说的两个*放在一起, 它的作用和程序里自带的那个叫做pow()的函数是完全相同的。
print(3 ** 2) # 输出: 9
print(pow(3, 2, 8)) # 输出: 1 (等价于(3**2) % 8)
2.2.2 关系运算符
关系运算符里包含了等于号、==以及!=, 它们可以被连接在一起使用, 其表达的意思与咱们在日常生活中所理解的那样是一样的。
# 等价于1 < 3 and 3 < 5
print(1 < 3 < 5) # 输出: True
# 比较列表的大小
print([1, 2, 3] < [1, 2, 4]) # 输出: True
# 字符串和数字不能比较
print('Hello' > 3) # 会抛出 TypeError
2.在第二点三这个部分里面, 我们要去说的是关于成员测试运算符以及同一性测试运算符这两个概念的详细介绍和说明。
成员测试运算符in用于进行成员测试这个操作, 也就是说, 它是用来检验一个对象是否为另一个对象的元素。同一性测试运算符is被用来判断两个对象是否为同一个对象, 如果这两个对象确实是同一个的时候将会返回True这个值, 否则如果它们不是同一个的话就会返回False这个对应的结果。
# 成员测试
print(3 in [1, 2, 3]) # 输出: True
print('a' in 'abcdefg') # 输出: True
# 同一性测试
x = [1, 2, 3]
y = x
print(x is y) # 输出: True
2.2.4 位运算符与集合运算符
位运算这个操作, 它是只能用来对付整数数据的。它内部那个执行的过程, 其实挺麻烦的。首先, 得先把那个整数转换成对应的二进制数形式。然后还得把这堆二进制的东西对齐了, 让它们右边对右边地对齐好。接着, 才肯乖乖地按位去进行各种运算工作。
等这些乱七八糟的都算完了, 最后再把得到的结果倒回去, 转换为咱们平时常用的十进制数字再返还出来。至于说集合里面的交集、并集、还有那种对称差集之类的运算, 全都是借助着位运算符的这些功能来实现的。但是要注意, 像差集这种特殊的东西, 可不走上面那条路, 而是直接使用减号那个运算符来完成计算的。
# 位运算
print(3 << 2) # 输出: 12
print(3 & 7) # 输出: 3
print(3 | 8) # 输出: 11
# 集合运算
print({1, 2, 3} | {3, 4, 5}) # 输出: {1, 2, 3, 4, 5}
print({1, 2, 3} & {3, 4, 5}) # 输出: {3}
2.2.5 逻辑运算符
逻辑方面, 运算符它包含有 and , 或者 or , 以及 not 这些。 and 与 or 它们是具有惰性求值这种特点, 也被称作逻辑短路的情况存在在内。而关于 not , 它的结果是一定会返回 True 或者是 False 的。
# 惰性求值
a = 5
print(3 > 5 and a > 3) # 输出: False
print(3 < 5 or a > 3) # 输出: True
# 返回最后一个计算的表达式的值
print(3 and 5) # 输出: 5
print(3 or 5) # 输出: 3
print(not 3) # 输出: False
2.在第2.6节中, 我们会介绍矩阵乘法运算符。
从版本3.5开始, 增加了一个新的矩阵相乘运算符@, 该运算符通常会与扩展库numpy一起使用。另外, @符号在某些情况下还用来表示修饰器的用法。
import numpy as np
x = np.ones(3)
m = np.eye(3) * 3
m[1, 2] = 5
m[2, 0] = 3
print(x @ m) # 矩阵相乘
2.这是第二点七部分, 关于补充说明的内容。
在表2-3中列出的那些运算符以外, 还存在赋值运算符, 同时也存在复合赋值运算符。这些运算符的典型例子包括+=、-=以及*=。系统不支持使用++这个运算符, 也不支持使用--这个运算符。从版本号3.8起, 新增了 := 这种赋值运算符。
i = 3
print(++i) # 输出: 3 (正正得正,等价于+(+i))
# Python不支持++运算符,语法错误
# print(i++) # SyntaxError
print(--i) # 输出: 3 (负负得正,等价于-( -i))
# Python不支持--运算符,语法错误
# print(i--) # SyntaxError
根据上文所述, 系统提供了十分丰富并且也具有一定灵活程度的运算符和表达式内容方面, 这些工具主要用来完成各式各样的复杂级别的计算活动以及逻辑判断环节, 在真正的编程操作过程中, 如果能够合理地运用好这些运算符号的话, 那么无疑可以在一定程度上让编写出来的代码变得更加简洁同时也更具可读性。