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

为何deepcopy weakref.proxy会复制目标对象?谁持有引用?与weakref.ref差异是否为预期?

关于weakref.proxy与weakref.ref的deepcopy行为差异解析

1. 行为差异的本质原因

你没有误解测试结果,这种差异是有意设计的,源于两者的定位完全不同:

  • weakref.proxy是透明代理对象:它的核心设计目标是让使用者能像操作原对象一样操作代理。当执行deepcopy时,copy模块会自动穿透代理,直接对原对象执行深拷贝,最终返回的是原对象的拷贝实例(而非代理的拷贝)。
  • weakref.ref是弱引用容器:它本身是一个独立的可调用对象,仅用于存储原对象的弱引用。对它执行deepcopy时,复制的只是这个容器本身,而非它指向的目标对象,因此拷贝后的引用仍然指向原对象。

2. 拷贝出的A实例未被GC的原因

proxy_deepcopy变量本身就是拷贝后的A实例(不是代理),它持有该实例的强引用。只要这个变量存在于当前作用域中,Python的垃圾回收机制就不会回收该实例。

3. 验证代码与结果解析

weakref.proxy的深拷贝行为

import copy
import weakref

class A:
    def __init__(self, val=3):
        self.val = val

    def identify(self):
        return id(self)

a = A()

proxy = weakref.proxy(a)
proxy.val = 4
proxy_deepcopy = copy.deepcopy(proxy)
proxy_deepcopy.val = 5

print(a.val, a.identify())                            # 4 139732708115984
print(proxy.val, proxy.identify())                    # 4 139732708115984
print(proxy_deepcopy.val, proxy_deepcopy.identify())  # 5 139732690146640

这里proxy_deepcopy是原对象a的独立深拷贝实例,和a拥有不同的内存地址,修改它的属性不会影响原对象。

weakref.ref的深拷贝行为

import copy
import weakref

class A:
    def __init__(self, val=3):
        self.val = val

    def identify(self):
        return id(self)

a = A()

proxy = weakref.ref(a)
proxy().val = 4
proxy_deepcopy = copy.deepcopy(proxy)
proxy_deepcopy().val = 5

print(a.val, a.identify())                                # 5 140323837493200
print(proxy().val, proxy().identify())                    # 5 140323837493200
print(proxy_deepcopy().val, proxy_deepcopy().identify())  # 5 140323837493200

这里proxy_deepcopy是原weakref.ref容器的拷贝,它指向的仍然是原对象a,因此通过它修改属性会直接作用在a上。

总结

  • weakref.proxy的深拷贝会穿透代理复制原对象,返回原对象的拷贝实例;weakref.ref的深拷贝仅复制引用容器,始终指向原对象。
  • 这种差异是有意设计的,完全符合两者的定位:一个是模拟原对象的透明代理,一个是管理弱引用的独立容器。
  • 拷贝后的A实例被proxy_deepcopy变量持有强引用,因此不会被立即回收。

内容的提问来源于stack exchange,提问作者mutableVoid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:03:10