Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

do not understand closures question in python

def a(b=[]):
    b.append(1)
    return b

print a()
print a()

All of a sudden i got a list with 2 elems, but how? Shouldn't b be getting set to empty list every time.

Thanks for the help

like image 960
oneeyedelf1 Avatar asked Dec 04 '10 21:12

oneeyedelf1


People also ask

Can you explain closures in Python?

Defining a Closure FunctionThis technique by which some data ( "Hello in this case) gets attached to the code is called closure in Python. This value in the enclosing scope is remembered even when the variable goes out of scope or the function itself is removed from the current namespace.

What is __ closure __ in Python?

A closure is a function object that remembers values in enclosing scopes even if they are not present in memory. The __closure__ attribute of a closure function returns a tuple of cell objects. This cell object also has an attribute called cell_contents, which returns returns the contents of the cell.

Why aren't Python nested functions closures?

This is because of how Python it manages the functions variable scope. While the inner function can read the outer function's variables, it cannot write them.

Which is true about closure in Python?

A closure is a nested function which has access to a free variable from an enclosing function that has finished its execution. Three characteristics of a Python closure are: it is a nested function. it has access to a free variable in outer scope.


4 Answers

Default arguments are only evaluated once, when the function is defined. It retains the same object from one invocation to the next, which means that the same list keeps getting appended to. Use a default value of None and check for that instead if you want to get around this.

like image 185
Ignacio Vazquez-Abrams Avatar answered Oct 25 '22 11:10

Ignacio Vazquez-Abrams


Nothing to do with closures, at least not in the usual sense.

The default value for b is not "a new empty list"; it is "this particular object which I just created right now while defining the function, initializing it to be an empty list". Every time the function is called without an argument, the same object is used.

like image 22
Karl Knechtel Avatar answered Oct 25 '22 13:10

Karl Knechtel


The corrected version, for the reasons given in other answers, is:

def a(b=None):
    b = [] if b is None else b

    b.append(1)
    return b
like image 44
SingleNegationElimination Avatar answered Oct 25 '22 13:10

SingleNegationElimination


default arguments are evaluated (once) when the function is defined, not each time it is called.

try this:

def a(b=None):
    if b is None
        b = []     
    b.append(1)
    return b

print a()
print a()
like image 44
Corey Goldberg Avatar answered Oct 25 '22 11:10

Corey Goldberg