Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

python - Persistence of references in the local namespace

It is generally the case that the variables in the local namespace (defined within the function scope) are destroyed when the function is finished executing. I read somewhere that under certain conditions they may persist to exist after the function finishes execution. Is it possible to enlist those cases under which this may be true.

To give a short example:

def foo (x):
    a = s*x
    return a 

When can references to apersist.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is possible if the variable defined in the local scope is referenced in an enclosed scope as a free variable, this will create a closure:

def foo():
    a = 42
    def bar():
        print(a)
    return bar

bar = foo()

So now, a reference persists after foo is done executing, because a is actually part of the closure created by bar:

>>> bar.__code__.co_freevars
('a',)
>>> bar.__closure__
(<cell at 0x7fbed0768af0: int object at 0x106f50110>,)

Note, this is handled differently by the bytecode, there are special op-codes STORE_DEREF/LOAD_DEREF to assign to and access variables in these closure cells:

>>> import dis
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (42)
              2 STORE_DEREF              0 (a)

  3           4 LOAD_CLOSURE             0 (a)
              6 BUILD_TUPLE              1
              8 LOAD_CONST               2 (<code object bar at 0x7fbed1c34660, file "<stdin>", line 3>)
             10 LOAD_CONST               3 ('foo.<locals>.bar')
             12 MAKE_FUNCTION            8 (closure)
             14 STORE_FAST               0 (bar)

  5          16 LOAD_FAST                0 (bar)
             18 RETURN_VALUE

Disassembly of <code object bar at 0x7fbed1c34660, file "<stdin>", line 3>:
  4           0 LOAD_GLOBAL              0 (print)
              2 LOAD_DEREF               0 (a)
              4 CALL_FUNCTION            1
              6 POP_TOP
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

Compared to STORE_FAST/LOAD_FAST:

>>> def foo():
...     a = 1
...     print(a)
...
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  3           4 LOAD_GLOBAL              0 (print)
              6 LOAD_FAST                0 (a)
              8 CALL_FUNCTION            1
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...