,= 运算符
The ,= operator
在查看一些 Python 代码时,我注意到使用了看起来像 ,=
运算符的东西:
a ,= b
经过实验和对 assignment statements syntax 的非常仔细的检查后,我开始意识到它实际上是 "tuple unpacking",左侧的长度为 1 的元组 a,
和集合 [=14] =] 在右边。所以在一个简单的情况下,它就像下面这样,但也适用于任何 iterables/generators:
assert len(b)
a = b[0]
我很好奇这个技巧是否有名字,是否有任何不那么晦涩的技巧可以达到相同的效果?
没有这样的运算符,它是带有目标列表的工厂assignment statement的普通运行。大多数人会使用不同的间距,a, = b
.
你看的是元组赋值(也叫拆包),左边可以有多个元素。请记住,是 逗号 使表达式计算为元组,而不是括号。单目标形式没有更具体的名称。
左边是一个只有一个元素的元组,a,
。然后右侧被解包,并且必须恰好包含一个元素,然后将其存储在 a
中。如果左侧有更多目标,则右侧必须有匹配数量的元素:
>>> 1, # a tuple with one element
(1,)
>>> a, = 1, # assigning one value to the left-hand targets.
>>> a
1
>>> a, b = 1, # not enough elements
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack
>>> a, b = 1, 2, 3 # the syntax requires an exact match, 3 is too many
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>> a, b = 1, 2 # two values assigned
>>> a
1
>>> b
2
对目标列表进行赋值是赋值运算符的一项正常且广泛使用的功能,即使不是每个人都意识到这可以与单元素元组一起用作目标。
该技术在处理 API 时很常用,它 总是 生成一个元组或列表,但您只需要一个值。一个典型的例子是数据库 API:
cursor.execute('SELECT id FROM TABLE WHERE condition LIMIT 1')
result_id, = cursor.fetchone()
数据库查询结果的每一行总是一个序列,即使您只选择了一列。
没有 'less obscure' 形式的技术,没有。知道了就不需要其他技巧了,也不再晦涩难懂!
声明;
a, = b
- 假设 b 是可迭代的
- 从 b 中获取第一个值并将其分配给 a(接近
a = b[0]
)
- 断言 b 没有更多值(即
len(b) == 1
)
在这个意义上它与 a = b[0]
不同。后者将与 b = ['a', 'b']
一起工作,而第一个将引发 ValueError: too many values to unpack
。另一边:
l = [x]
it = iter(l)
a, = it #fine when a=it[0] raises TypeError: 'listiterator' object has no attribute '__getitem__'
TL/DR:如果 b 是一个列表或一个只有一个元素的元组,a, = b
和 a = b[0]
的行为相同,但在其他情况下它们的行为可能不同
在查看一些 Python 代码时,我注意到使用了看起来像 ,=
运算符的东西:
a ,= b
经过实验和对 assignment statements syntax 的非常仔细的检查后,我开始意识到它实际上是 "tuple unpacking",左侧的长度为 1 的元组 a,
和集合 [=14] =] 在右边。所以在一个简单的情况下,它就像下面这样,但也适用于任何 iterables/generators:
assert len(b)
a = b[0]
我很好奇这个技巧是否有名字,是否有任何不那么晦涩的技巧可以达到相同的效果?
没有这样的运算符,它是带有目标列表的工厂assignment statement的普通运行。大多数人会使用不同的间距,a, = b
.
你看的是元组赋值(也叫拆包),左边可以有多个元素。请记住,是 逗号 使表达式计算为元组,而不是括号。单目标形式没有更具体的名称。
左边是一个只有一个元素的元组,a,
。然后右侧被解包,并且必须恰好包含一个元素,然后将其存储在 a
中。如果左侧有更多目标,则右侧必须有匹配数量的元素:
>>> 1, # a tuple with one element
(1,)
>>> a, = 1, # assigning one value to the left-hand targets.
>>> a
1
>>> a, b = 1, # not enough elements
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 1 value to unpack
>>> a, b = 1, 2, 3 # the syntax requires an exact match, 3 is too many
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>> a, b = 1, 2 # two values assigned
>>> a
1
>>> b
2
对目标列表进行赋值是赋值运算符的一项正常且广泛使用的功能,即使不是每个人都意识到这可以与单元素元组一起用作目标。
该技术在处理 API 时很常用,它 总是 生成一个元组或列表,但您只需要一个值。一个典型的例子是数据库 API:
cursor.execute('SELECT id FROM TABLE WHERE condition LIMIT 1')
result_id, = cursor.fetchone()
数据库查询结果的每一行总是一个序列,即使您只选择了一列。
没有 'less obscure' 形式的技术,没有。知道了就不需要其他技巧了,也不再晦涩难懂!
声明;
a, = b
- 假设 b 是可迭代的
- 从 b 中获取第一个值并将其分配给 a(接近
a = b[0]
) - 断言 b 没有更多值(即
len(b) == 1
)
在这个意义上它与 a = b[0]
不同。后者将与 b = ['a', 'b']
一起工作,而第一个将引发 ValueError: too many values to unpack
。另一边:
l = [x]
it = iter(l)
a, = it #fine when a=it[0] raises TypeError: 'listiterator' object has no attribute '__getitem__'
TL/DR:如果 b 是一个列表或一个只有一个元素的元组,a, = b
和 a = b[0]
的行为相同,但在其他情况下它们的行为可能不同