Python中的自分配安全吗



这些天这个问题让我很困惑:当一个变量在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,如果一个对象可以从一个作用域访问,它就不会被垃圾收集。

最新更新