func = []
for value in range(5):
func.append(lambda: print_index(value))
def print_index(index_to_print):
print(index_to_print)
for a in func:
a()
When I run the code above, the output is
4
4
4
4
4
Why is it not ?
0
1
2
3
4
What can I do to make it like the above.
I have tried importing copy and using copy.deepcopy(index). I didn't work probably since index is an integer.
Is lambda part of the reason it is not working.
Thank you for your help!
Not quite sure what you are trying to achieve but the reason that it is printing all 4s is because Python uses dynamic name resolution of variables, that is the value of value when the functions are executed (not when it is declared) is used.
If you really need a function to print the value then you need to create a closure, which means creating the function inside another function, e.g.:
def make_closure(v):
return lambda: print_index(v)
func = []
for value in range(5):
func.append(make_closure(value))
Now this outputs:
In []:
for a in func:
a()
Out[]:
0
1
2
3
4
As #AChampion said, Python calculates the value of value when it needs to and not while executing the loop.
However for me it seemed easier to do the following fix.
func = []
for value in range(5):
func.append(lambda v = value: print_index(v))
def print_index(index_to_print):
print(index_to_print)
for a in func:
a()
This is setting the default argument in the function which gets calculated during the loop execution. The code above is the same as saying :
func = []
for value in range(5):
def anonymous_function(v=value):
print_index(v)
func.append(anonymous_function)
def print_index(index_to_print):
print(index_to_print)
for a in func:
a()
Related
I have a recursive function like this:
b=4
def someFunction(x,y,z):
global b
b += x
if...#something
else:
someFunction(x,y,z)
...
Theres a lot to it, but thats the general idea. My issue is that when running my program on cmd, I cant keep calling 'someFunction' with different parameters as there is no reset for b, however if I reset b within the function It won't work as I intend it to. So I could write this in two functions with the recursion in a sub function, but is there some other way to have b reset when I call the function without this being a problem when it starts recursion?
What I usually do is use an optional keyword argument, like this.
def someFunction(x,y,z, b=None):
if b is None:
b = 4
b += x
if...#something
else:
someFunction(x,y,z,b=b)
This way you can initialize the b on the first call to any value (and avoid usage of global variables).
This also has the positive that now someFunction is a pure function (no side effects and same input always gives same output) and much easier to work with. (Testing, refactoring, ..)
You can add an optional parameter of the function with the reset value:
def someFunction(x,y,z, reset = None):
if reset is not None:
b=reset
...
b += x
if...#something
else:
someFunction(x,y,z)
then the first time just call f(x,y,z, reset=4)
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 5 years ago.
In Python, the following code prints '0', not '1'.
def inc(x):
x = x+1
a = 0
inc(a)
print(a)
I understand why this happens; it's because integers are immutable. What I don't understand is how to get around this behaviour when it's undesirable. Suppose we want to create a new command such that the code
a = 0
inc(a)
print(a)
prints '1'.
Obviously, the naive approach won't do it. What can we do instead?
Similar (a bit more general) question can be found here along with a discussion how Python passes params to functions. In short, without making x variable in your code an object, I believe there's nothing we can do. Of course, you can alter your code to e.g. return changed value from function inc() and print that (i.e. print(inc(x))) or just do the printing from inside the inc() method, but that's not what you're essentially looking for.
If I understand correctly, You are trying to increment variable a using function inc(var) and passing 'a' as a external variable to the function inc().
As #Marko Andrijevic stated, variable x passed to function inc() and variable x defined in the function are different . One way to achieve is by returning value of x and collecting externally, which you may not be looking for.
Alternately, Since you have defined variable 'a' outside function ,it can be called global variable.
If you want to pass that to a function, and manipulate it, you need to define that variable ('a' in your case) inside the function as global. Something like below.
def inc(x):
global a
a = x+1
Now when the new value assigned to 'a' after 'x+1', it is retained after execution of 'inc(x)'
>>> a = 0
>>> inc(a)
>>> a
1
EDIT -1
As per comments by #DYZ . Its correct. declaring global a inside inc() function will always increment a.
A better alternative will be , in that case, to return x inside inc() and assign that value to any external variable.
Not an elegant solution, but works as intended.
def inc(x):
return x+1
Result
>>> a
0
>>> a = inc(a)
>>> a
1
>>> a = inc(a)
>>> a
2
>>> b = 0
>>> b = inc(b)
>>> b
1
>>> a
2
>>>
one can use yield to get variable values.
def inc(x,y,z):
x += 1
y+=1
z+=1
yield x,y,z #inc doesn't stop
yield x+y+z
a=b=c=0
gen=inc(a,b,c)
gen=list(gen)
a,b,c,sum=gen[0]+(gen[1],) #however, index must still be known
print a,b,c,sum
I have a problem where I need to pass the index of an array to a function which I define inline. The function then gets passed as a parameter to another function which will eventually call it as a callback.
The thing is, when the code gets called, the value of the index is all wrong. I eventually solved this by creating an ugly workaround but I am interested in understanding what is happening here. I created a minimal example to demonstrate the problem:
from __future__ import print_function
import threading
def works_as_expected():
for i in range(10):
run_in_thread(lambda: print('the number is: {}'.format(i)))
def not_as_expected():
for i in range(10):
run_later_in_thread(lambda: print('the number is: {}'.format(i)))
def run_in_thread(f):
threading.Thread(target=f).start()
threads_to_run_later = []
def run_later_in_thread(f):
threads_to_run_later.append(threading.Thread(target=f))
print('this works as expected:\n')
works_as_expected()
print('\nthis does not work as expected:\n')
not_as_expected()
for t in threads_to_run_later: t.start()
Here is the output:
this works as expected:
the number is: 0
the number is: 1
the number is: 2
the number is: 3
the number is: 4
the number is: 6
the number is: 7
the number is: 7
the number is: 8
the number is: 9
this does not work as expected:
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
the number is: 9
Can someone explain what is happening here? I assume it has to do with enclosing scope or something, but an answer with a reference that explains this dark (to me) corner of python scoping would be valuable to me.
I'm running this on python 2.7.11
This is a result of how closures and scopes work in python.
What is happening is that i is bound within the scope of the not_as_expected function. So even though you're feeding a lambda function to the thread, the variable it's using is being shared between each lambda and each thread.
Consider this example:
def make_function():
i = 1
def inside_function():
print i
i = 2
return inside_function
f = make_function()
f()
What number do you think it will print? The i = 1 before the function was defined or the i = 2 after?
It's going to print the current value of i (i.e. 2). It doesn't matter what the value of i was when the function was made, it's always going to use the current value. The same thing is happening with your lambda functions.
Even in your expected results you can see it didn't always work right, it skipped 5 and displayed 7 twice. What is happening in that case is that each lambda is usually running before the loop gets to the next iteration. But in some cases (like the 5) the loop manages to get through two iterations before control is passed to one of the other threads, and i increments twice and a number is skipped. In other cases (like the 7) two threads manage to run while the loop is still in the same iteration and since i doesn't change between the two threads, the same value gets printed.
If you instead did this:
def function_maker(i):
return lambda: print('the number is: {}'.format(i))
def not_as_expected():
for i in range(10):
run_later_in_thread(function_maker(i))
The i variable gets bound inside function_maker along with the lambda function. Each lambda function will be referencing a different variable, and it will work as expected.
A closure in Python captures the free variables, not their current values at the time of the creation of the closure. For example:
def capture_test():
i = 1
def foo():
return i
def bar():
return i
print(foo(), bar()) # 1 1
i = 2
print(foo(), bar()) # 2 2
In Python you can also capture variables and write to them:
def incdec():
counter = 0
def inc(x):
nonlocal counter
counter += x
return counter
def dec(x):
nonlocal counter
counter -= x
return counter
return inc, dec
i1, d1 = incdec()
i2, d2 = incdec()
print(i1(10), i1(20), d1(3)) # 10 30 27
print(i2(100), d2(5), d2(20)) # 100 95 75
print(i1(7), d2(9)) # 34 66
As you see incdec returns a pair of two closures that captured the same variable and that are incrementing/decrementing it. The variable shared by i1/d1 is however different from the variable shared by i2/d2.
One common mistake is for example to expect that
L = []
for i in range(10):
L.append(lambda : i)
for x in L:
print(x())
will display the numbers from 0 to 9... all of the unnamed closures here captured the same variable i used to loop and all of them will return the same value when called.
The common Python idiom to solve this problem is
L.append(lambda i=i: i)
i.e. using the fact that default values for parameters are evaluated at the time the function is created. With this approach each closure will return a different value because they're returning their private local variable (a parameter that has a default).
Python beginner question. Say you want to dynamically create a function that keeps some state (in the code below an integer i). Then as the function defined is an object, we could use it later on. In the following code, I add the functions to a list, and each call to print(fn(0)) should result in 0 1 2 3 4, but instead I get 4 4 4 4 4 as if only the latest value of i is used.
fns = []
for i in range(5):
def fn(x):
return x + i
fns += [fn]
print(fns)
for fn in fns:
print(fn(0))
quit()
Is it possible to accomplish in Python what this code tries to do?
To work around the late binding issue, you can use default keyword parameter:
for i in range(5):
def fn(x, i=i): # <-----
return x + i
....
A function that retains its own state? I would do it like this:
class func:
# can behave as a function, but can also hold its own value
def __init__(self, value=0):
self.value = value
# this function is the actual 'function' that is called each time
def __call__(self, arg):
self.value += arg
return self.value
fns = []
for i in range(5):
# create new function, and give it a starting value of i
fn = func(i)
fns += [fn]
for fn in fns:
print( fn(0) )
The result is 0 1 2 3 4
#!/usr/bin/python3
class BubbleSort:
def __init__(self):
self.x=[]
self.limit=0
def getElements(self):
self.limit=int(input("Enter the limit:"))
print("Enter {} number".format(self.limit))
for i in range(1,self.limit+1):
self.x.append(int(input()))
def sort(self):
for i in range(0,self.limit):
for j in range(0,(self.limit-1)-i):
if self.x[j+1] < self.x[j]:
temp1=self.x[j+1]
temp2=self.x[j]
del self.x[j]
del self.x[j+1]
self.x.insert(j+1,temp2)
self.x.insert(j,temp1)
print(self.x)
print("Sorted list is")
for i in self.x:
print(i)
def main():
b=BubbleSort()
b.getElements()
b.sort()
if __name__=="__main__":main()
This is a simple bubble sort program.
Problem 1: If I run the program, two same numbers come , for example, when i enter say -> 3 6 5 1 2
output -> 1 2 2 5 6
The 3 gets replaced by 2.
2: why do I see a lot of 'self' as parameter to a function in python? then what does self.x=[] and self.limit=0 do?
I am super new to methods as a concept and I tried reading, they do not help.
3.In the function getElements, what is self.limit ? why is it even required? we can just use a normal variable like 'x'
Ex: x= int(input("enter the limit:"))
print("enter {} number".format(x))
3.Explain the self.x.append(int(input())))
Doesnt append(int(something)) will add the value of something in the end of a list?
Check the for loop, say the self.limit is 5(entered value). then the loop requires 6 numbers right? equivalence in c++
for(i=1;i<=6;i++)
Assuming the left most number is not considered in python in the range function. right?
Mainly explain 'self' parameter in every function.
When you delete x[j], x[j+1] becomes x[j]. Replace:
del self.x[j]
del self.x[j+1]
with:
del self.x[j+1]
del self.x[j]
However, like #IanAuld said, deleting elements of an array while iterating over it is poor programming practice. Instead, try making a new array and copying the elements to the new array, leaving the original array unchanged in the process. Afterward, if you want, you can replace the old array with the new array.
And to answer your second question, self refers to the class so you can access other variables from the same class your function is in. For example, if you have:
#!/usr/bin/python3
class Foo:
bar = 3
def getValueOfBar(self):
return self.bar
x = Foo()
print( x.getValueOfBar() )
self refers to the parent class, so you can retrieve variables from the class that aren't in the scope of the function.