python performs a deepcopy of a weakref.proxy's content. Why? Which entity owns the reference?

76 Views Asked by At

I wanted to double check my assumption, that the content of a weakref.proxy is not deepcopied when performing a deepcopy of it. To that end, I wrote the following code snippet:

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

However my assumption seems to be incorrect; a deepcopy of a is performed when deepcopying the proxy. Am I misinterpreting the results of the tests or do I have a misconception of how the weakref.proxy is supposed to work? Shouldn't the copied instance of A be immediately be GCed?

I checked on the internet and found that the expected behavior occurs when using weakref.ref instead of the weakref.proxy (which I thought was mainly semantic sugar).

Because of this line in the CPython copy module that I found reading up on this stack overflow answer on weakref.ref utilizing weakref.ref yields the results I would have expected:

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

Is this discrepancy between weakref.proxy and weakref.ref intended?

Who is the owner of the deepcopied instance of A, that is still accessible through the proxy_deepcopy?

Executed with CPython 3.8.18 and 3.10.13.

0

There are 0 best solutions below