简体   繁体   中英

locals() and object reference in python

I found something curious about how python tracks objects in locals() .

Considering the following script:

import gc


class T(object):
    pass


def func1():

    t = T()

    #locals()
    del t
    #locals()

    for o in gc.get_objects():
        if type(o) is T:
            print("STILL EXISTS")


func1()

Running with both locals() calls commented (as above) gives me no messages, indicated that the T() object created was garbage collected.

When I run it with the first locals() command (removing the first comment), it seems to create a dictionary that contains a reference to my t object. This dictionary is not associated to any names, so I wouldn't expect this dict to live as without being garbage collected.

The problem is that, running the code, I get "STILL EXISTS" . Even if I delete t from the function namespace, the object is not garbage collected as the dict returned by locals() is still referring to it.

Funny enough, if I call locals() again (removing the second comment in the code above), then somehow the dictionary gets updated, it does not contain t in it and the object is garbage collected successfully (and I don't get an "STILL EXISTS" message).

I find this behaviour a bit weird.

Questions are:

  1. Is it normal that the dictionary returned by locals() is long lived, even without associating it with any names?
  2. Is it normal or is there any reason that this dictionary does not get updated automatically when deleting names from the current scope?

Edit: I am using cpython 3.6

Thanks!

locals() is weird. Inside a function, every locals() call copies the current local variable values into a dict associated with the stack frame and returns the dict. The dict is not used for actual local variable lookup, but it is attached to the frame object, and it is not a new dict every time; all locals() calls in the same stack frame reuse the same dict.

When you call locals() , the locals dict now has a reference to all objects currently referred to by local variables. This will keep those objects alive until either the stack frame dies, or a new locals() call is made inside that stack frame with different local variable values. A few other things will also update the locals dict, such as retrieving the f_locals attribute of the stack frame object, but local variable assignment does not update the locals dict by itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM