python variable scope in nested functions

2024/10/7 0:13:11

I am reading this article about decorator.

At Step 8 , there is a function defined as:

def outer():x = 1def inner():print x # 1return inner

and if we run it by:

>>> foo = outer()
>>> foo.func_closure # doctest: +ELLIPSIS

it doesn't print x. According to the explanation :

Everything works according to Python’s scoping rules - x is a localvariable in our function outer. When inner prints x at point #1 Pythonlooks for a local variable to inner and not finding it looks in theenclosing scope which is the function outer, finding it there.

But what about things from the point of view of variable lifetime? Ourvariable x is local to the function outer which means it only existswhile the function outer is running. We aren’t able to call inner tillafter the return of outer so according to our model of how Pythonworks, x shouldn’t exist anymore by the time we call inner and perhapsa runtime error of some kind should occur.

However, I don't really understand what the second paragraph means.

I understand inner() does get the value of x but why it doesn't print x out?

thanks

UPDATE:

Thanks all for the answers. Now I understand the reason. the "return inner" is just a pointer to inner() but it doesn't get executed, that is why inner() doesn't print x as it is not called at all

Answer

I understand inner() does get the value of x but why it doesn't printx out?

It doesn't print out anything because you've not called the inner function yet.

>>> def outer():x = 1def inner():print x # 1return inner
...     
>>> func = outer()  
>>> func            
<function inner at 0xb61e280c>
>>> func()
1

This is called a closure, i.e even though the outer function is not in stack(finished executing) anymore but still the inner function that was returned from it remembers it's state.(i.e value of x)

>>> def outer():x = 1y = 2def inner():z=3print xreturn inner
...     
>>> func = outer()
>>> func.func_code.co_freevars  #returns the variables that were used in closure
('x',)

From the source code on how python decides it's a closure or not:

   459    if len(code.co_freevars) == 0:460        closure = NULL461    else:462        len(closure) == len(code.co_freevars)

In py3.x you can also modify the value of x using nonlocal statement inside inner function.

>>> def outer():x = 1def inner():nonlocal xx += 1print (x)return inner
...     
>>> func = outer()
>>> func()
2
>>> func()
3
>>> func()
4
https://en.xdnf.cn/q/70306.html

Related Q&A

How can I throttle Python threads?

I have a thread doing a lot of CPU-intensive processing, which seems to be blocking out other threads. How do I limit it?This is for web2py specifically, but a general solution would be fine.

get lastweek dates using python?

I am trying to get the date of the last week with python. if date is : 10 OCT 2014 meansIt should be print10 OCT 2014, 09 OCT 2014, 08 OCT 2014, 07 OCT 2014, 06 OCT 2014, 05 OCT 2014, 04 OCT 2014I trie…

Why is vectorized numpy code slower than for loops?

I have two numpy arrays, X and Y, with shapes (n,d) and (m,d), respectively. Assume that we want to compute the Euclidean distances between each row of X and each row of Y and store the result in array…

Handle TCP Provider: Error code 0x68 (104)

Im using this code to sync my db with the clients:import pyodbcSYNC_FETCH_ARRAY_SIZE=25000# define connection + cursorconnection = pyodbc.connect()cursor = connection.cursor()query = select some_column…

vectorized radix sort with numpy - can it beat np.sort?

Numpy doesnt yet have a radix sort, so I wondered whether it was possible to write one using pre-existing numpy functions. So far I have the following, which does work, but is about 10 times slower tha…

Which library should I use to write an XLS from Linux / Python?

Id love a good native Python library to write XLS, but it doesnt seem to exist. Happily, Jython does.So Im trying to decide between jexcelapi and Apache HSSF: http://www.andykhan.com/jexcelapi/tutoria…

put_records() only accepts keyword arguments in Kinesis boto3 Python API

from __future__ import print_function # Python 2/3 compatibility import boto3 import json import decimal#kinesis = boto3.resource(kinesis, region_name=eu-west-1) client = boto3.client(kinesis) with ope…

Setting a transparent main window

How to set main window background transparent on QT? Do I need an attribute or a style? Ive tried setting the opacity, but it didnt work for me. app.setStyleSheet("QMainWindow {opacity:0}"

Elementwise division of sparse matrices, ignoring 0/0

I have two sparse matrices E and D, which have non-zero entries at the same places. Now I want to have E/D as a sparse matrix, defined only where D is non-zero.For example take the following code:impor…

Django import export Line number: 1 - uColumn id not found

I am trying to import excel documents into a Django DB. I have added the following code to admin.py and model.py. There seems to be an error in the development of Django. I have read through several di…