python - 元组赋值什么时候表现得像所涉及的变量的“交换”,什么时候表现得像“单独的顺序赋值”?
问题描述
下面,我用三个例子来说明“交换”和“赋值语句的顺序执行”的含义。
示例 1(交换)
元组赋值可以非常方便地交换变量的内容。
下面的例子展示了我们如何在不需要临时变量的情况下以清晰简洁的方式交换数组中两个元素的内容:
a = [1,2]
# prints [1, 2]
print(a)
a[0], a[1] = a[1], a[0]
# prints: [2,1] and not: [2, 2] as with a sequential assignment!
print(a)
该示例向我们展示了元组赋值如何表现得像交换,而不是顺序执行第一个赋值,然后进行第三个赋值。
示例 2(交换)
这是另一个交换三个整数的示例:
x, y, z = 1, 2, 3
# prints: 1 2 3
print(x, y, z)
# swap contents in variables:
x, y, z = z, y, x
# prints: 3 2 1 and not: 3 2 3 as with a sequential assignment!
print(x, y, z)
示例 3(顺序赋值语句)
然而,一旦事情变得比简单数据类型更复杂,元组赋值也可能表现得像顺序赋值。
让我们考虑以下链表实现:
class ListNode:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __repr__(self):
is_first = True
current = self
l = []
safety_count = 0
while current and safety_count < 10:
if not is_first:
l.append(' -> ')
is_first = False
l.append(str(current.data))
current = current.next
safety_count += 1
return ''.join(l)
def __str__(self):
return self.__repr__()
这个函数颠倒了链表的顺序(并且工作得很好):
def reverse_list_working(L):
if not L:
return L
pre_current = None
current = L
while True:
tmp_next = current.next
current.next = pre_current
pre_current = current
current = tmp_next
if not current:
break
return pre_current
现在,我们可能会想通过元组赋值来摆脱 tmp_ 变量,以交换变量的内容:
def reverse_list_not_working(L):
pre_current = None
current = L
while True:
pre_current, current, current.next = current, current.next, pre_current
if not current:
break
return pre_current
但是,一旦我们到达最后一个元素,这种实现就会出错。这里的问题是元组赋值的行为类似于顺序赋值。
- 分配:pre_current -> 当前
- 分配:current -> current.next(在列表末尾是 None )
- assign: current.next -> pre_current : 产生错误,因为 current 是 None!
解决方案
这是另一个用伪代码总结元组分配如何工作的答案:
以下元组赋值:
a, b, c = e1, e2, e3
被翻译成:
e1_ = eval(e1)
e2_ = eval(e2)
e3_ = eval(e3)
a = e1_
b = e2_
c = e3_
因此,请注意,如果更改访问的某些共享状态,e1
则表达式的评估可能会对表达式的评估产生影响。e2
e1
e2
类似地,分配 toa
可能会影响b
, if的分配b
取决于 a (例如, a = c
, b = c.next
)。
因此,元组分配不仅仅是“交换”。
例子:
班级编号:
def __init__(self, val):
self.val = val
def __add__(self, other):
return Num(self.val + other)
def __str__(self):
return str(self.val)
类计数器:
def __init__(self):
self.val = Num(1)
def get_and_increment(self):
return_val = self.val
self.val += 1
return return_val
c = 计数器()
a = Num(1) a.val = Num(2) b = a
a.val, b.val = c.get_and_increment(), c.get_and_increment()
print(str(a)) # -> 打印 2 print(str(b)) # -> 打印 2
推荐阅读
- reactjs - 在 spfx 中使用 Material-UI 时出现很多错误
- keras - Keras 单输入多输出 - 为什么与单输出相比损耗如此之高?
- python - python:按数据框中的一列用户对象分组
- amazon-web-services - S3-从本地系统担任角色
- github - 将 github npm 包从私有更改为公共
- css - 自定义字体在 Safari 或 Firefox 上不起作用
- c++ - 动态编程不会检索我期望的所有值
- android - 如何在 MotionLayout 中定义使内容从屏幕外部显示的过渡?
- python - Lxml 和 python:仅迭代现有元素
- mysql - SQL查询未达到条件