这些天这个问题让我很困惑:当一个变量在Python中被分配给自己时会发生什么?例如,
a = a if (a>b) else b
我对引用计数机制知之甚少,对这个问题一无所知。如果你知道答案,请帮帮我,谢谢!
完全安全。Python将对=
符号之后的所有内容进行排序,以便在分配变量之前计算表达式我认为在任何编程语言中,这都是不安全的(请参阅下面@hadik的评论(。
自赋值时,该变量的引用计数会发生什么?
简而言之,它会做正确的事情。
在一个更长的答案中,要回答这个问题,最好通过运行以下代码来查看反汇编:
import dis
def f(a, b):
a = a if (a>b) else b
dis.dis(f)
带注释的拆卸:
# the objects pointed by `a` and `b` starts with a positive refcount as they're part of the function argument
# increment refcount for the object pointed by `a` and `b`
0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
# COMPARE_OP (usually) returns boolean True/False
# increment the refcount of the boolean value
# and decrement the refcount of the object pointed by `a` and `b`
4 COMPARE_OP 4 (>)
# decrements the refcount of that boolean value
6 POP_JUMP_IF_FALSE 12
# increment refcount for the object pointed by `a`
8 LOAD_FAST 0 (a)
10 JUMP_FORWARD 2 (to 14)
# increment refcount for the object pointed by `b`
>> 12 LOAD_FAST 1 (b)
# decrement refcount for the object originally pointed by `a`
>> 14 STORE_FAST 0 (a)
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
一些背景信息:PythonVM是一个堆栈机器。LOAD_*操作将一个值推送到堆栈(并增加其refcount,因为堆栈现在有了对对象的引用(,大多数其他操作将从堆栈中弹出值并将计算结果推送到堆栈中(减少消耗值的refcount并增加结果(。STORE_*操作将对象从堆栈顶部移动到变量(并减少变量引用的原始对象的refcount;它不需要更改被移动对象的refcount,因为从堆栈弹出并设置为变量实际上不会更改refcount(。
简而言之,Python refcount总是做正确的事情,即使是在多线程的情况下(这要归功于GIL(。你真的不应该担心refcount,如果一个对象可以从一个作用域访问,它就不会被垃圾收集。