You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中简单赋值是否会对变量进行两次求值?

验证Python简单赋值与增强赋值的求值次数差异

要验证普通赋值(如x = x + 1)中x被求值两次,核心是让x的求值过程带有可观测的副作用,且x需是复杂表达式(如属性引用、下标操作)——简单局部变量的求值无明显副作用,无法直接观测次数差异。以下是两种有效验证方法:


方法1:带副作用的下标键调用

利用下标操作的键为带计数副作用的函数,直观展示求值次数:

count = 0

def get_key():
    global count
    count += 1
    print(f"get_key 被调用,次数: {count}")
    return 'a'

d = {'a': 1}

# 测试增强赋值
print("=== 增强赋值 d[get_key()] += 1 ===")
d[get_key()] += 1
print(f"增强赋值后计数: {count}")  # 输出1,仅调用一次get_key

# 重置计数,测试普通赋值
count = 0
print("\n=== 普通赋值 d[get_key()] = d[get_key()] + 1 ===")
d[get_key()] = d[get_key()] + 1
print(f"普通赋值后计数: {count}")  # 输出2,调用两次get_key

原理

增强赋值中,d[get_key()]这个表达式仅被求值一次:既用来获取当前值,也用来确定赋值目标;而普通赋值中,右边的d[get_key()]是一次求值(获取值),左边的d[get_key()]是另一次求值(确定赋值位置),因此触发两次函数调用。


方法2:带副作用的属性访问拦截

自定义类,通过__getattribute__拦截所有属性访问(包括赋值前的目标查找),统计访问次数:

class TestObj:
    def __init__(self):
        self._x = 1
        self.access_count = 0

    def __getattribute__(self, name):
        # 拦截x属性的所有访问(读取、赋值前查找)
        if name == 'x':
            self.access_count += 1
            print(f"访问属性x,次数: {self.access_count}")
        return super().__getattribute__(name)

    def __setattr__(self, name, value):
        # 避免内部属性赋值触发计数混乱
        if name in ('_x', 'access_count'):
            super().__setattr__(name, value)
        else:
            # 赋值x时会先触发__getattribute__查找目标
            super().__setattr__(name, value)

# 测试增强赋值
print("=== 增强赋值 obj.x += 1 ===")
obj1 = TestObj()
obj1.x += 1
print(f"增强赋值后访问次数: {obj1.access_count}")  # 输出1

# 测试普通赋值
print("\n=== 普通赋值 obj.x = obj.x + 1 ===")
obj2 = TestObj()
obj2.x = obj2.x + 1
print(f"普通赋值后访问次数: {obj2.access_count}")  # 输出2

原理

__getattribute__会在每次访问x时计数:

  • 普通赋值中,右边读取obj.x触发一次计数,左边查找obj.x作为赋值目标再触发一次计数;
  • 增强赋值中,obj.x仅被访问一次,同时完成值的获取和赋值目标的确定。

为什么你之前的测试未达预期?

  1. 简单局部变量:局部变量的求值只是栈帧中的加载/存储操作,无明显副作用,无法观测两次求值的区别;
  2. 仅统计读取副作用:若用property的getter仅统计值的读取,普通赋值只会触发一次getter(右边读取),左边赋值不会触发getter,导致计数与增强赋值一致,无法体现差异。

内容的提问来源于stack exchange,提问作者An old man in the sea.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 19:14:52