03.1 各种赋值语句
- 赋值语句建立对象引用值。
Python赋值语句会把对象引用值存储在变量名或数据结构的元素内。赋值语句总是建立对象的引用值,而不是复制对象。因此,Python变量更像是指针,而不是数据存储区域。
- 变量名在首次赋值时会被创建。
Python会在首次将值(即对象引用值)赋值给变量时创建其变量名。有些(并非全部)数据结构元素也会在赋值时创建(例如,字典中的元素,一些对象属性)。一旦赋值了,每当这个变量名出现在表达式时,就会被其所引用的值取代。
- 变量名在引用前必须先赋值。
使用尚未进行赋值的变量名是一种错误。如果你试图这么做,Python会引发异常,而不是返回某种模糊的默认值;如果返回默认值,就很难在程序中找出输入错误的地方。
- 执行隐式赋值的一些操作。
除=语句之外,在Python中,赋值语句会在许多情况下被隐式使用。例如,模块导入、函数和类的定义、for循环变量以及函数参数全都是隐式赋值运算。因为赋值语句在任何出现的地方的工作原理都相同,所有这些环境都是在运行时把变量名和对象的引用值绑定起来而已。
spam = 'Spam'
序列(包括字符串、元组及列表)分解赋值
spam, ham = 'yum', 'YUM'
[spam, ham] = ['yum', 'YUM']
a, b, c, d = 'spam'
当在“=”左边编写元组或列表时,Python会按照位置把右边的对象和左边的目标根据位置从左至右相配对。例如第一个中,字符串’yum’赋值给变量名spam,而变量名ham则绑定至字符串’YUM’。
从内部实现上来看,Python会先在右边制作元素的元组,所以这通常被称为元组分解赋值语句。分解赋值语句必须满足右边的元素个数等于左边的变量个数,其次右边可以为任何的可迭代对象。
分解赋值语句也是一种交换两变量的值,却不需要自行创建临时变量的方式:右侧的元组会自动记住先前的变量的值。例如a,b=b,a
分解赋值语句可以使用嵌套:((a, b), c) = ('SP', 'AM')
变量列表中某一个变量使用*前缀+变量名的方式表示,这种情况下,可以实现等号两边元素个数不一致的情况。此时,会将等号右表所有剩余的元素以列表的形式赋值给带星号的变量。
>>> a,b,*c=1,2,3,4,5,6
>>> a,b,c
(1, 2, [3, 4, 5, 6])
>>> a,*b,c=1,2,3,4,5,6
>>> a,b,c
(1, [2, 3, 4, 5], 6)
>>> *a,b,c=1,2,3,4,5,6
>>> a,b,c
([1, 2, 3, 4], 5, 6)
注意:扩展的序列解包时,等号左边不能同时出现≥2个带星号的变量,并且带星号的变量不能单独出现,必须以序列元素的形式出现。如(*a,)、[*a]、*a
>>> *a = 1,2,3
File "<stdin>", line 1
SyntaxError: starred assignment target must be in a list or tuple
>>> (*a,) = 1,2,3
>>> a
[1, 2, 3]
多目标赋值语句就是直接把所有提供的变量名都赋值给右侧的对象。这种情况下,多个变量名都会指向同一个内存对象。
例如,下面把三个变量a、b和c赋值给字符串’spam’:
>>> a = b = c = 'spam'
>>> a, b, c
('spam', 'spam', 'spam')
这种形式相当于这三个赋值语句,但更为简单:
>>> c = 'spam'
>>> b = c
>>> a = b
X += Y X &= Y
X -= Y X |= Y
X *= Y X ^= Y
X /= Y X >>= Y
X %= Y X <<= Y
X **= Y X //= Y
说明:
共享引用时,应注意“+=”对列表是做原处修改,完全不像“+”合并,总是生成新对象。
list3=list1=[1,2]
list1+=list2 等同于list1.append(list2),而不是list1=list1+list2
>>> a = ''
>>> b = a or 4 #如果变量a的值为空,则将4赋值给b
>>> b
4