1 先来个例子:
Python 还可以完成比二加二更复杂的任务。 例如,可以编写 斐波那契数列 的初始子序列,如下所示:
>>> # 斐波那契级数:
... # 两个元素的和定义了下一个值
... a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8
这个例子中出现了循环,赋值,比较,输出。
1,第一行中的 多重赋值:变量 a 和 b 同时获得新值 0 和 1。最后一行又用了一次多重赋值,这体现 在右表达式在赋值前就已经求值了。右表达式求值顺序为从左到右。
2,while 循环只要条件保持为真就会一直执行(这里指: a < 10 )。
3,Python 和 C 一样,任何非零整数都 为真,零为假。这个条件也可以是字符串或列表的值,事实上,任何序列都可以;长度非零就为真,空序列则为 假。示例中的判断只是最简单的比较。
4,比较操作符的标准写法和 C 语言一样: < (小于)、 > (大 于)、 == (等于)、 <= (小于等于)、 >= (大于等于)及 != (不等于)。
5, 循环体是缩进的 :缩进是 Python 组织语句的方式。在交互式命令行里,得为每个缩进输入制表符或空格。 使用文本编辑器可以实现更复杂的输入方式;所有像样的文本编辑器都支持自动缩进。交互式输入复合语句时, 要在最后输入空白行表示结束(因为解析器不知道哪一行代码是最后一行)。注意,同一块语句的每一行的缩进相同。
6,print() 函数输出给定参数的值。与表达式不同,它能处理多个参数,包括浮 点数与字符串。它输出的字符串不带引号,且各参数项之间会插入一个空格,这样可以实现更好的格式化操作:
>>> i = 256*256
>>> print('The value of i is', i)
The value of i is 65536
2 赋值
python赋值语句的特性:
变量在首次赋值时会被创建,不必提前预声明变量名;
变量在引用前必须先赋值;
执行隐式赋值的一些操作,如: 模块导入、函数和类的定义、函数参数、for循环变量。
赋值语句创建对象引用,而不是对象复制;比如下面的示例,a和b是两个变量,b最初的值由a赋值得到,但它们都指向同一个对象(这里是下面的编程名言字符串),b重新赋值之后,其指向改变了,内存地址不再与a相同。
>>> a = '学习赋值'
>>> b = a
>>> id(a)
2895823313616
>>> id(b)
2895823313616
>>> id(a) == id(b)
True
>>> b = '1'
>>> id(b)
2895823206960
>>> id(a) == id(b)
False
2.1 常量逻辑赋值,等号赋值
python中不支持常量类型,但是可以在程序的逻辑上进行定义,需要告诉自己他是不能改的(常用全大写字母表示),
>>> MAX_SPEED=120
>>> print(MAX_SPEED)
120
>>> MAX_SPEED=140
>>> print(MAX_SPEED)
140
>>>
等号( = )用于给变量赋值。赋值后,下一个交互提示符的位置不显示任何结果:
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
2.2 序列赋值:
>>> x,y,z = 1,2,3
>>> x
1
>>> y
2
>>> z
3
我们可以看作:x = 1,y = 2,z = 3
2.3 链接赋值:
>>> x = y = 1
>>> x
1
>>> y
1
>>> print(id(1)) # 打印地址
2895821865200
>>> print(id(x))
2895821865200
>>> print(id(y))
2895821865200
分别打印1,x,y 3个值得内存地址,执行的结果是一样的。说明变量x和y都是存储了整数对象1的引用地址。
2.4 增量赋值。
比如x = x + 1 我们可以改成x+=1
>>> x=5
>>> x = 5
>>> x = x + 1
>>> x
6
>>> x = 5
>>> x += 1
>>> x
6
调用这些方法来实现扩展算术赋值 ( += , -= , *= , @= , /= , //= , %= , **= , <<= ,>>= , &= , ^= , |= )。这些方法应该尝试进行自身操作 (修改 self) 并返回结果 (结果应该但并非必须为 self)。
2.5 解包赋值
系列数据赋值给对应相同个数的变量,个数必须保持一致
>>>a,b,c = 123
>>>a
1
>>>b
2
>>>c
3
>>>
>>>a,b = 1,2 # 使用系列解包赋值实现变量交换
>>>a,b = b,a
>>>print(a,b)
2 1
>>>
2.6 赋值表达式
新增的语法 := 可在表达式内部为变量赋值。又被昵称为海象表达式
在这个示例中,赋值表达式可以避免调用 len() 两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:
while (block := f.read(256)) != '':
process(block)
另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:
[clean_name.title() for name in names
if (clean_name := normalize('NFC', name)) in allowed_names]
类似的益处还可出现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于
提取子分组:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。
3 比较运算
比较运算符是指两个数据之间的比较运算。
比较运算符有6个:>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、==(等于)和!=(不等于)

与 C 不同,Python 中所有比较运算的优先级相同,低于任何算术、移位或位运算。 另一个与 C 不同之处在于a < b < c 这样的表达式会按传统算术法则来解读。
比较运算可以任意串连,例如 x < y <= z 等价于 x < y and y <= z ,除了 y 只被求值一次(但在两种写法下当 x < y 值为假时 z 都不会被求值)。
正式的说法是这样:如果 a, b, c, …, y, z 为表达式,而 op1, op2, …, opN 为比较运算符,则 a op1 b op2 c … y opN z 就等价于 a op1 b and b op2 c and … y opN z ,不同点在于每个表达式最多只被求值一次。
请注意 a op1 b op2 c 不意味着在 a 和 c 之间进行任何比较,因此,如 x < y > z 这样的写法是完全合法的(虽然也许不太好看)。
3.1 值比较
运算符 < , > , == , >= , <= 和 != 将比较两个对象的值。 两个对象不要求为相同类型。
对象都有相应的值(还有类型和标识号)。 对象值在 Python 中是一个相当抽象的概
念:例如,对象值并没有一个规范的访问方法。 而且,对象值并不要求具有特定的构建方式
。 比较运算符实现了一个特定的对象值概念。 人们可以认为这是通过实现对象比较间接地定义了对象值。由于所有类型都是 object 的(直接或间接)子类型,它们都从 object 继承了默认的比较行为。 类型可以通过实现 丰富比较方法 例如 lt() 来定义自己的比较行为。
默认的一致性比较 ( == 和 != ) 是基于对象的标识号。 因此,具有相同标识号的实例一致性比较结果为相等,具有不同标识号的实例一致性比较结果为不等。 规定这种默认行为的动机是希望所有对象都应该是自反射的 (即
x is y 就意味着 x == y )。
次序比较 ( < , > , <= 和 >= ) 默认没有提供;如果尝试比较会引发 TypeError 。 规定这种默认行
为的原因是缺少与一致性比较类似的固定值。按照默认的一致性比较行为,具有不同标识号的实例总是不相等,这可能不适合某些对象值需要有合理定义并有基于值的一致性的类型。 这样的类型需要定制自己的比较行为,实际上,许多内置类型都是这样做的。
比较运算符多用于数值型数据比较,有时也用字符串数据比较,比较结果是布尔值True或False。
用比较运算符连接的表达式称为关系表达式,一般在程序分支结构中使用
>>> x='student'
>>> y='teacher'
>>> x>y
False
>>> len(x) == len(y)
True
>>> x!=y
True
>>> x+y==y+x
False
需要注意的是,比较运算符两端可以有多余的空格(当然也可以没有),但是中间不能有空格((指两个符号的运算符==、!=、<>、>=、<=),会产生语法错误“SyntaxError: invalid syntax”。
需要特别说明的比较运算符是等于比较运算符,因为一个等号已被用作最为重要的赋值运算符了,相对次要的等于比较操作就使用两个等于号表示,这是C系列语言的通用做法。
C、C++、C#、Java、JavaScript等语言中均是如此。在C系列语言中,赋值运算符也是有返回值的,它返回赋值运算符右边的值,所以C系列语言中无法根据是否需要返回值来判断表达式中的等于号是比较运算符还是赋值运算符,这是赋值号与等于号使用两套不同符号的原因。
不过在B系列语言中,比如Visual Basic、VBScript、按键精灵、易语言中,等于比较运算符和赋值运算符都使用一个等于号表示——系统根据表达式出现的位置自动判断是赋值运算符还是等于比较运算符。
B系列语言的赋值运算符没有返回值,所以可以根据是否需要返回值,来判断表达式中的等于号是比较运算符还是赋值运算符。
Python采用了C系列语言的赋值运算符和等于比较运算符不同的语法,但是它的赋值运算符和B系列语言一样,没有返回值。两个等于号(==)可用于判断两个数值是否相等,也可判断两个字符串是否一样。
3.2 内置类型比较行为
以下描述了最主要内置类型的比较行为。
1、内置数值类型 (数字类型 —- int, float, complex) 以及标准库类型 fractions.Fraction 和decimal.Decimal
可进行类型内部和跨类型的比较,例外限制是复数不支持次序比较。 在类型相关的限制以
内,它们会按数学(算法)规则正确进行比较且不会有精度损失。
非数字值 float(‘NaN’) 和 decimal.Decimal(‘NaN’) 属于特例。 任何数字与非数字值的排序比较均返回假值。 还有一个反直觉的结果是非数字值不等于其自身。 举例来说,如果 x = float(‘NaN’) 则 3 <
x , x < 3 和 x == x 均为假值,而 x != x 则为真值。
2、None 和 NotImplemented 都是单例对象。 建议单例对象的比较应当总是通过 is 或 is not 而不是等于运算符来进行。
3、二进制码序列 ( bytes 或 bytearray 的实例) 可进行类型内部和跨类型的比较。 它们使用其元素的数字值按字典顺序进行比较。
4、字符串 ( str 的实例) 使用其字符的 Unicode 码位数字值 (内置函数 ord() 的结果) 按字典顺序进
行比较。字符串和二进制码序列不能直接比较。
5、序列 ( tuple , list 或 range 的实例) 只可进行类型内部的比较,range 还有一个限制是不支持
次序比较。 以上对象的跨类型一致性比较结果将是不相等,跨类型次序比较将引发 TypeError 。
序列比较是按字典序对相应元素进行逐个比较。 内置容器通常设定同一对象与其自身是相等的。 这使得它们能跳过同一对象的相等性检测以提升运行效率并保持它们的内部不变性。
6、内置多项集间的字典序比较规则如下:
6.1两个多项集若要相等,它们必须为相同类型、相同长度,并且每对相应的元素都必须相等(例如, [1,2]== (1,2) 为假值,因为类型不同)。
6.2对于支持次序比较的多项集,排序与其第一个不相等元素的排序相同(例如 [1,2,x] <= [1,2,y] 的值与x <= y 相同)。 如果对应元素不存在,较短的多项集排序在前(例如 [1,2] < [1,2,3] 为真值)。
7、两个映射 ( dict 的实例) 若要相等,必须当且仅当它们具有相同的 (键, 值) 对。 键和值的一致性比较强制规定自反射性。
次序比较 ( < , > , <= 和 >= ) 将引发 TypeError 。
8、集合 ( set 或 frozenset 的实例) 可进行类型内部和跨类型的比较。
它们将比较运算符定义为子集和超集检测。 这类关系没有定义完全排序(例如 {1,2} 和 {2,3} 两个集
合不相等,即不为彼此的子集,也不为彼此的超集。 相应地,集合不适宜作为依赖于完全排序的函数的参数(例如如果给出一个集合列表作为 min() , max() 和 sorted() 的输入将产生未定义的结果)。
集合的比较强制规定其元素的自反射性。
9、大多数其他内置类型没有实现比较方法,因此它们会继承默认的比较行为。
10、在可能的情况下,用户定义类在定制其比较行为时应当遵循一些一致性规则(Python 并不强制要求这些一致性规则。 实际上,非数字值就是一个不遵循这些规则的例子。):
10.1 相等比较应该是自反射的。 换句话说,相同的对象比较时应该相等:
x is y 意味着 x == y
10.2 比较应该是对称的。 换句话说,下列表达式应该有相同的结果:
x == y 和 y == x
x != y 和 y != x
x < y 和 y > x
x <= y 和 y >= x
10.3 比较应该是可传递的。 下列例子显示了这一点:
x > y and y > z 意味着 x > z
x < y and y <= z 意味着 x < z
10.4 反向比较应该导致布尔值取反。 换句话说,下列表达式应该有相同的结果:
x == y 和 not x != y
x < y 和 not x >= y (对于完全排序)
x > y 和 not x <= y (对于完全排序)
3.2 标识号比较
运算符 is 和 is not 用于检测对象的标识号:当且仅当 x 和 y 是同一对象时 x is y 为真。 一个对
象的标识号可使用 id() 函数来确定。 x is not y 会产生相反的逻辑值。
本文介绍了Python3.10中的赋值和比较运算,包括多重赋值、序列赋值、链接赋值、增量赋值、解包赋值和赋值表达式等赋值特性,并详细讲解了比较运算,如值比较、内置类型比较行为,以及标识号比较,探讨了等号和双等号在Python中的作用和不同。

4万+

被折叠的 条评论
为什么被折叠?



