Python: function in for-loop 'header' - python

I have a function that returns a list of integers.
def my_function(param: int)->list:
do_sth...
return list
In another module i have a for loop that iterates trough the returned list of that function.
Now my Question is:
for x in my_function(x):
do_sth...
does the for-loop call this function every loop or only one time at the begin?

Actually the answer is invoke only once, when you do the following things:
for x in my_function(x):
do_sth...
my_function(x) will be evaluated first, and then it return a list, so the statement is like this:
for x in [...]:
do_sth...
you can add a print function in my_function body, and you will see that the print function is invoked only once.

This is indeed a duplicate of this question. However, for the sake of a clearer explanation (credit #Nathan) without getting into technical jargon, here is an example:
>>> def a():
... print("a() was called")
... return [1, 2, 3, 4, 5]
...
>>> for i in a():
... print(i)
...
a() was called
1
2
3
4
5
As you can see here, the function a() was only called once when the for loop was run.
Hope this helped!

Related

Python dereference closure variable at define-time

The answer in this post details nicely how python inner functions don't use the value of closure variables until the inner function actually executes, finding the variable name in the proper scope.
For example:
funcs = [(lambda: x) for x in range(3)]
Calling any of the generated lambdas returns 2:
>>> funcs[0]()
2
>>> funcs[1]()
2
>>> funcs[2]()
2
Is there a way to force the value for x to be determined when the function is defined instead of when it is executed later? In the above example, my desired output is 0, 1, 2, respectively.
More specifically, my use-case is to provide a way for API users to conveniently turn a custom function into a thread using a decorator. For example:
for idx in range(3):
#thread_this(name=f'thread_{idx}')
def custom():
do_something()
print(f'thread_{idx} complete.')
When the final print statement executes, it picks up whatever the current value of idx is in the global scope. With appropriate sleep statements, all 3 threads will print 'thread_2 complete.'
You can use functools.partial, first problem can be solved with,
funcs = [functools.partial(lambda x: x, x) for x in xrange(3)]
It will give you desired result.
However, I could not understand the second usecase.

yield statement in myhdl

I have the following code in my myhdl environment:
def rst(self):
rst.next=rst.active
self.wait_clks(5)
def wait_clks(self, cycles):
for _ in range(cycles):
yield self.clk.posedge
the above code doesn't work but when I replace it with the following it works:
def rst(self):
rst.next=rst.active
for _ in range(5):
yield self.clk.posedge
I am confused over this, if anyone can explain why the yield in the function definition doesn't work?
When you simply call a generator function (one that has yield statement in its body) , you get a generator object, it does not even start going through the function at that point, it only starts that when you start iterating over the returned generator object (or call next() on it). Example -
>>> def gen1():
... print("Starting")
... for i in range(10):
... yield i
...
>>> g = gen1()
>>> g
<generator object gen1 at 0x00273E68>
As you can see above, it did not start going through the function, it just returned the generator object. To go through the function you need to iterate over g or call next() on it. Example -
>>> g.next()
Starting
0
>>> for i in g:
... print i
...
1
2
.
.
In your first case as well something similar is happenning, you are just calling the generator function, which returns the generator object, and then discarding the result. Most probably, from wherever rst() is called , it is expecting a generator object in return. In which case your second method is the best.
But if you really really want to make it in a separate function (and I do not see any need to make it in a separate method) , you can directly return the result of self.wait_clks(5) back from rst(self) . Example -
def rst(self):
rst.next=reset.active
return self.wait_clks(5)
Example to show that this works -
>>> def f():
... return gen1()
...
>>> for i in f():
... print(i)
...
Starting
0
1
2
.
.
As described by Anand you can't simply call a generator, in this case if you yield the generator you will get what you expect"
def rst(self):
rst.next=rst.active
yield self.wait_clks(5)

Python closures using lambda

I saw this below piece of code in a tutorial and wondering how it works.
Generally, the lambda takes a input and returns something but here it does not take anything and still it works.
>>> for i in range(3):
... a.append(lambda:i)
...
>>> a
[<function <lambda> at 0x028930B0>, <function <lambda> at 0x02893030>, <function
<lambda> at 0x028930F0>]
lambda:i defines the constant function that returns i.
Try this:
>>> f = lambda:3
>>> f()
You get the value 3.
But there's something more going on. Try this:
>>> a = 4
>>> g = lambda:a
>>> g()
gives you 4. But after a = 5, g() returns 5. Python functions "remember" the environment in which they're executed. This environment is called a "closure". By modifying the data in the closure (e.g. the variable a in the second example) you can change the behavior of the functions defined in that closure.
In this case a is a list of function objects defined in the loop.
Each of which will return 2.
>>> a[0]()
2
To make these function objects remember i values sequentially you should rewrite the code to
>>> for i in range(3):
... a.append(lambda x=i:x)
...
that will give you
>>> a[0]()
0
>>> a[1]()
1
>>> a[2]()
2
but in this case you get side effect that allows you to not to use remembered value
>>> a[0](42)
42
I'm not sure what you mean by "it works". It appears that it doesn't work at all. In the case you have presented, i is a global variable. It changes every time the loop iterates, so after the loop, i == 2. Now, since each lambda function simply says lambda:i each function call will simply return the most recent value of i. For example:
>>> a = []
>>> for i in range(3):
a.append(lambda:1)
>>> print a[0]()
2
>>> print a[1]()
2
>>> print a[2]()
In other words, this does not likely do what you expect it to do.
lambda defines an anonymous inline function. These functions are limited compared to the full functions you can define with def - they can't do assignments, and they just return a result. However, you can run into interesting issues with them, as defining an ordinary function inside a loop is not common, but lambda functions are often put into loops. This can create closure issues.
The following:
>>> a = []
>>> for i in range(3):
... a.append(lambda:i)
adds three functions (which are first-class objects in Python) to a. These functions return the value of i. However, they use the definition of i as it existed at the end of the loop. Therefore, you can call any of these functions:
>>> a[0]()
2
>>> a[1]()
2
>>> a[2]()
2
and they will each return 2, the last iteration of the range object. If you want each to return a different number, use a default argument:
>>> for i in range(3):
... a.append(lambda i=i:i)
This will forcibly give each function an i as it was at that specific point during execution.
>>> a[0]()
0
>>> a[1]()
1
>>> a[2]()
2
Of course, since we're now able to pass an argument to that function, we can do this:
>>> b[0](5)
5
>>> b[0](range(3))
range(0, 3)
It all depends on what you're planning to do with it.

How to pass predefined arguments when storing a function

Is it possible to store a function with predefined arguments to be called by another function?
For example:
def function(num):
print num
trigger=function #store function(1)
trigger() #prints 1
trigger=function #store function(2)
trigger() #prints 2
trigger calls whatever is stored without passing any arguments. I can change trigger but that would require me to rewrite the function that calls the trigger, so I'm wondering if there is a way to store functions along with arguments when storing a function in a variable.
You're looking for functools.partial:
>>> import functools
>>> def foo(number):
... print number
...
>>> bar = functools.partial(foo, 1)
>>> bar()
1
Someone already mentioned functools.partial which is preferred, but you can also use lambda functions without arguments:
trigger1 = lambda: function(1)
trigger2 = lambda: function(2)
Note: As someone mentioned, be careful about defining functions like this in loops or by referencing any value in the lambda body that might change.
You might end up in a situation like this:
a = []
for i in range(5):
a.append(lambda: i)
b = [func() for func in a]
# equals [4, 4, 4, 4, 4]
# to avoid this, do a.append(lambda i=i: i)

Will the function in python for loop be executed multiple times?

Say I have the following class with a method returning a list:
class C:
def f(self):
return [1,2,3]
If I loop over the list returned fro the method, as follows:
c = C()
for i in c.f():
print(i)
Inside the for loop, will c.f() be executed multiple times? If yes, in order to get it once, do I have to do assignment outside of the loop, or there is some trivial way?
In [395]: def tester():
...: print "Tester Called!"
...: return [1,2,3]
In [396]: for i in tester():
...: pass
Tester Called!
Seems the answer is no.
from the python docs:
The for statement is used to iterate over the elements of a sequence
(such as a string, tuple or list) or other iterable object:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
The expression list is evaluated once; it should yield an iterable object.
c.f() will not get executed multiple times.
You didn't ask, but you might be curious about generators.
Your example as a generator would be as follows:
class C:
def f():
yield 1
yield 2
yield 3
The loop where you iterate over the results would be unchanged.
It will be executed only once. But there will be syntax errors in your code:
class , not Class
def f(self), not def f()
Did you try to test it yourself? The answer to your question is NO.
Here is how you should have tested it. Moreover there were lot of flaws in your code. Check the self commented modified version below
>>> class C: #its class not Class and C not C()
def f(self): #You were missing the self argument
print "in f" #Simple Test to validate your query
return [1,2,3]
>>> c=C()
>>> for i in c.f():
print i
in f
1
2
3
>>>
Though this example is trivial but still I will use this as an example to explain how we can leverage the power of functional programming of Python. What I will try to explain is called lazy evaluation or generator functions(http://docs.python.org/glossary.html#term-generator).
Consider the modified example
>>> class C: #its class not Class and C not C()
def f(self): #You were missing the self argument
print "in f" #Simple Test to validate your query
for i in [1,2,3]:
yield i #Generates the next value when ever it is requsted
return #Exits the Generator
>>> c=C()
>>> for i in c.f():
print i
in f
1
2
3
>>>
Can you spot the difference?
No it is executed once.
And your method is not correctly defined. Should have a self argument:
class C:
def f(self):
return [1,2,3]

Categories

Resources