Pra*_*ota 5 python binding namespaces variable-assignment
如何将不可变对象的名称重新绑定到扩充赋值的结果?
对于可变对象,例如,if x = [1, 2, 3]和y = [4,5],那么当我们执行x + = y时,它会被执行,因为x.__iadd__(y)它会x 在适当的位置进行修改,并且名称x会再次重新绑定到它吗?
当它x是不可变的时,它是如何工作的?以下是Python文档对扩充分配的看法.
如果x是一个没有定义
__iadd__()方法的类的实例,x.__add__(y)并且y.__radd__(x)被考虑,就像评估一样x + y.
OK,现在如果x = (1, 2, 3)和y = (4, 5)当我们这样做x += y,蟒蛇执行x.__add__(y)这将创建一个新的对象.但是,当这又如何新对象获得反弹到x?
我去的CPython特别是源代码洞穴探险tuple对象(tupleobject.c)和AugAssign部分在Python的ast.c和ast.c,但不能真正了解重新绑定是如何发生的.
编辑:删除原始问题中的误解,并将其更改为问题形式,以防止混淆未来的读者.
Sve*_*ach 11
像一条线
x += y
Run Code Online (Sandbox Code Playgroud)
实际上翻译为相当于
x = x.__iadd__(y)
Run Code Online (Sandbox Code Playgroud)
重新绑定总是发生,即使x是可变的.如果__iadd__()以执行就地操作的方式实现,则需要返回self,并且名称将反弹到它指向的对象.如果__iadd__()没有实现,可以使用常用的添加方法,__add__()或者__radd__()在帖子中注明.
这就是x += y函数内部呈现x本地名称的原因.(说明:在Python中,如果函数内部有此名称的赋值,则该函数x += y被视为函数的本地名称. 被视为赋值x,因此x被视为包含此类行的函数的本地名称.请参阅此文章由Eli撰写Bendersky了解更多信息.)
这种行为的另一个例子:
t = ([], 1)
t[0] += [1]
Run Code Online (Sandbox Code Playgroud)
导致错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)
但无论如何都会附上清单.这是因为首先list.__iadd__()调用,更改列表.接下来,t[0] = <list object>尝试,导致错误.
有关语义的详细文档可以在Python语言参考和PEP 203中找到.引用前者:
增强赋值评估目标(与正常赋值语句不同,它不能是解包)和表达式列表,执行特定于两个操作数上的赋值类型的二进制运算,并将结果赋给原始目标.目标仅评估一次.
像x + = 1这样的增强赋值表达式可以重写为x = x + 1,以实现类似但不完全相等的效果.在增强版本中,x仅评估一次.此外,在可能的情况下,实际操作是就地执行的,这意味着不是创建新对象并将其分配给目标,而是修改旧对象.