How can I loop over function calls in Python? - python

So I am not sure if this can be done at all, but was curious anyway. Let us suppose I have the following piece of code:
def statement1():
# Do something
def statement2():
# Do something
def statement3():
# Do something
statement1()
statement2()
statement3()
Now, as you can see here, I have to execute all the above functions one after the other. They are also named in a similar fashion, so that made me wonder- is there a way to loop over function calls?
I basically want to have something like a for loop which loops over 'statements', and I don't end up calling each one again and again with only a slight modification in the name.
A side note- I am new to the community so feel free to give me feedback on how to ask and comment on the answers, would go a long way in helping me.
Thanks in advance!

You can use globals() with fstring if the function name is always follow the specific pattern
def statement1():
print("s1")
def statement2():
print("s2")
def statement3():
print("s3")
for i in range(3):
globals()[f"statement{i+1}"]()
Output:
s1
s2
s3

Try this:
def st1():
return 'Hi 1'
def st2():
return 'Hi 2'
def st3():
return 'Hi 3'
list1 = [st1(), st2(), st3()]
for word in list1:
print(word)

Here is a way if you don't want to use globals:
import sys
def statement1():
print(1)
def statement2():
print(2)
def statement3():
print(3)
for i in range(1, 4):
f_name = 'statement{}'.format(i)
getattr(sys.modules[__name__], f_name)()

#deadshot has provided one option how it can be done. On the other hand, if you want to design it this way, I guess this is because you plan that the standard usage will require running all three functions in this exact order? In this case the more classic way would be to define a main function:
def statement1():
# Do something
def statement2():
# Do something
def statement3():
# Do something
def main():
statement1()
statement2()
statement3()
if __name__ == '__main__':
main()

If the functions to similar things, you usually do this via arguments:
def statement(arg):
# do something with arg
for i in range(3):
statement(i)

Consider using this one eval() built in function in python; you could even use eval() when you want to pass parameters to the functions as you can see bellow. However, you should be careful when using eval with the OS module imported and taking input from the user with input() since eval() runs and executes everything it receives.
def statement1(num):
print("Statement_{} -> number-{}".format(num, num))
def statement2(num):
print("Statement_{} -> number-{}".format(num, num))
def statement3(num):
print("Statement_{} -> number-{}".format(num, num))
for i in range(3):
eval("statement{}({})".format(i+1, i+1))
Output would look like:
Statement_1 -> number-1
Statement_2 -> number-2
Statement_3 -> number-3

You can choose the functions which have sign word,the run the choosed functions use vars() or globals() dict.
def statement1():
print("s1")
def statement2():
print("s2")
def statement3():
print("s3")
functionSign = 'statement'
for varName in list(vars().keys()):
if functionSign in varName:
vars()[varName]()
Output:
s1
s2
s3

Below is solution. It is inelegant but will work. Please wait for an elegant solution to appear.
import re
def statement1():
# Do something
print("Statement 1")
def statement2():
# Do something
print("Statement 2")
def statement3():
# Do something
print("Statement 3")
for i in dir():
if re.fullmatch(r'^__[a-zA-Z0-9_]*__$' , i):
continue
else:
if re.fullmatch(r'^statement[0-9]*$',i):
eval('%s()'%i)
The output is
Statement 1
Statement 2
Statement 3

Functions are objects as well so you can used them as variables. Something like:
fns = [statement1, statement2, statement3]
for fn in fns:
fn()

Related

Can generator be used through polymorphism

I don't even know if it is the proper way to put it, but I recently had trouble while trying to use a method from an object, both as a map engine (mapping closure to elements of an iterator) and as a generator of generator.
I is probably much more simple to explain this through a code example:
class maybe_generator():
def __init__(self, doer):
self.doer = doer
def give(self):
for i in [1,2,3]:
self.doer(i)
def printer(x):
print('This is {}'.format(x))
def gener(x):
yield(x)
p = maybe_generator(printer)
p.give()
g = maybe_generator(gener)
print('Type of result is {}'.format(g.give()))
Output is
This is 1
This is 2
This is 3
Type of result is None
I would have expected the g object ot be of type generator instead of NoneType. Then I wonder how it is possible to implement a function that can potentially generate a generator, or directly perform some border effect on the iterable.
Thank you in advance for your help
Ok, I finally found what I was looking for. having a function that works both as a mapping engine and a genrator may be possible with some hacks/tricks, but what I wanted in my use case was essentially getting a recursive generator.
This can be easily done with the keyword
yield from
The code now looks like something like that:
class maybe_generator():
def __init__(self, doer):
self.doer = doer
def give(self):
for i in [1,2,3]:
yield from self.doer(i)
def gener(x):
yield(x)
g = maybe_generator(gener)
gen = g.give()
print('Type of result is {}'.format(gen))
for k in gen:
print('value is {}'.format(k))
It was actually also worth taking a look at this advanced series of course on generator and coroutines: http://dabeaz.com/coroutines/

Python: calling def from a different def [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am relatively new to Python and I've been stuck on something that seems very trivial, so hoping someone can help.
What I'm trying to do is call a method inside a method in Python. I want to call this method several times, in various different methods, so I don't want to have to keep on copying and pasting the code if I'm going to be using it ~10 times - just to keep calling that "def".
I have tried things such as:
return anotherMethod()
Any ideas how to do this?!
Thanks!
Edit:
Sorry about the vagueness of the question. I'm trying to get my head around the terminology.
def scaleC():
pianoIcon = Icon("PianoScaleC.png")
d1 = Display("iPiano", pianoIcon.getWidth(), pianoIcon.getHeight())
d1.add(pianoIcon)
return piano()
def scaleCS():
pianoIcon = Icon("PianoScaleCS.png")
d1 = Display("iPiano", pianoIcon.getWidth(), pianoIcon.getHeight())
d1.add(pianoIcon)
return piano()
def piano:
#play the piano keys, etc
So you are doing something like this?:
def my_global_function():
def my_local_function():
print('hello world')
my_local_function()
And then outside of that definition you want to call that function again?
But it has been destroyed because you exited the scope.
You can make it a global then:
my_local_function_global_scope = None
def my_global_function():
def my_local_function():
print('hello world')
# Declare variable space as global and assign to it
global my_local_function_global_scope
my_local_function_global_scope = my_local_function
my_local_function()
my_local_function_global_scope()
SO you want to call the same function/method ten times? Do it in a loop eh?
for i in range(10):
print('Iteration Number %s' % i)
anotherMethod()
if you want to return the results of the function ten times in a list, you can use list comprehension
return [anotherMethod() for _ in range(10)]
Note: the _ variable is a convention used when you are required to have an assignment but you do not want to store that variable, naming it _ will effectively delete it as I understand.
my last idea is that you wan to reference the callable once and call it ten times. You can do that too (And its one of my favorite things about python)
my_method = anotherMethod
my_method()
my_method()
...
my_method()
my_method()
If you are asking on how to define methods in Python that can be called from everywhere you can write the method you want on a library.py file like this:
def fun(a , b):
return a + b
and then call it from another file (ie. program.py) like this:
from library import fun
def main():
# your code
print fun(1, 2)
a = 4
b = 5
c = fun(a, b)
print c
if __name__ == '__main__': main()
this will output:
3
9
hope that helps.
Well it is quite simple. You just literally call that function inside your other function. Here is an example:
def Examples():
print 'Function successfully called!'
def Example()
print 'Calling function...'
Examples() #This will call the function above it
Example()
Your result should be:
Calling function...
Function successfully called!
No errors should pop up and this should work. Just add a variable:
loop = 0
and put the functions in a while loop:
while loop <> 10:
loop += 1
def Examples():
print 'Function successfully called!'
def Example()
print 'Calling function...'
Examples() #This will call the function above it
Example()
This will should solve your problem. I hope this helps you! Your final code with this implied should be:
loops = 0
while loops <> 10:
loops += 1
def scaleC():
pianoIcon = Icon("PianoScaleC.png")
d1 = Display("iPiano", pianoIcon.getWidth(), pianoIcon.getHeight())
d1.add(pianoIcon)
piano()
def scaleCS():
pianoIcon = Icon("PianoScaleCS.png")
d1 = Display("iPiano", pianoIcon.getWidth(), pianoIcon.getHeight())
d1.add(pianoIcon)
piano()
def piano:
#play the piano keys, etc
If I understand your question right, you just need to use it like this.
class YourClass(object):
def method(self):
pass # here goes your method
def method_where_i_want_to_use_other_method(self):
self.method()
#other things you need in this method

How should I call functions defined outside of the main function?

So I'm fairly new to python and I am working on an algorithm and I have let's say 2 functions
func1(x)
func2(x)
already defined outside the main function.
Now I want to call these functions inside the main functions one nested inside the other
Something like this
def funcmain(func1(func2(x)))
It obviously is not working I haven't been able to get it work anyway I want. Any tips on this?
Edit: What I meant to do is that I want to input a string, I want it to go through func2 first, then the return value from func2 to go through func1 and finally the return value of func1 to go through func main. I have tested each function separately and they are working as intended but I can't seem to get them interlinked together
I hope this code snippet will help to clarify things for you.
#!/usr/bin/python
def func1(x):
return x + 1
def func2(x):
return x + 2
def main(x):
print func1(func2(x))
if __name__ == '__main__':
main(0)
The output is 3.
Is this what you mean? Your question is not too clear. I assume x is also defined globally somewhere.
def funcmain():
return func1(func2(x))
take the following functions:
def func1(x):
return x+1
def func2(x):
return x*2
by itself you COULD do this: func1(func2(3)) which would return 3 times 2 plus 1. This works because by itself func1(func2(3)) actually returns a value, not a function.
BUT since you are trying to put it as the basic argument for the main function like this:
def main(func1(func2(x))): #dont do this, this is what you did, it is bad
return x*3
its not going to know what to do with that because there is no default for x...
you CAN DO THIS THOUGH:
def main(x=func1(func2(1)):
return x*3
this would do the appropriate math to 1 and then assign it as x (Because as we saw earlier, func1(func2(3))` would return THE RESULT OF FUNCTIONS not a function itself, then multiply it by 3. since you are defaulting x to equal a value ( which is func1(func2(1))
This is bad practice still, because you are defaulting to whatever func1(func2(1) comes out to.
what you probably want in the end is something simpler:
def main(x):
y = func1(func2(x))
return y*3
or maybe even simpler than that
def main(x):
return x*3
#and then just call it like this
main(func1(func2(1))

How to use a map with *args to unpack a tuple in a python function call

I am currently doing a merge over a set of variables that I'd like to parallelize. My code looks something like this:
mergelist = [
('leftfile1', 'rightfile1', 'leftvarname1', 'outputname1'),
('leftfile1', 'rightfile1', 'leftvarname2', 'outputname2')
('leftfile2', 'rightfile2', 'leftvarname3', 'outputname3')
]
def merger(leftfile,rightfile,leftvarname,outvarname):
do_the_merge
for m in mergelist:
merger(*m)
Ordinarily, to speed up long loops, I would replace the for m in mergelist with something like....
from multiprocessing import Pool
p = Pool(8)
p.map(merger(m), mergelist)
p.close()
But since I'm using the star to unpack the tuple, it's not clear to me how to map this correctly. How do I get the *m?
Use lambda:
with Pool(8) as p:
p.map(lambda m:merger(*m), mergelist)
You can unpack the tuple in your merge function:
def merger(args):
if len(args) != 4:
# error
leftfile,rightfile,leftvarname,outvarname = args
do_the_merge
The other option is to unpack in the argument list:
def merger( (leftfile,rightfile,leftvarname,outvarname) ):
do_the_merge
Edit: to address the OP concerns:
def merger((l,r,v,o)):
return l+r
for m in mergelist:
print merger(m)
returns
leftfile1rightfile1
leftfile1rightfile1
leftfile2rightfile2
The simplest solution IMHO is to change the merger function, or add a wrapper:
def merger(leftfile,rightfile,'leftvarname','outvarname'):
do_the_merge
def merger_wrapper(wrapper_tuple):
merger(*wrapper_tuple)
p.map(merger_wrapper, mergelist)
I see #delnan actually also put this solution in the comments.
To add a little value to this :) You could also wrap it like this:
from functools import partial
def unpack_wrapper(f):
def unpack(arg):
return f(*arg)
return unpack
This should let you simplify this to
p.map(unpack_wrapper(merger), mergelist)

Go through a number of functions in Python

I have an unknown number of functions in my python script (well, it is known, but not constant) that start with site_...
I was wondering if there's a way to go through all of these functions in some main function that calls for them.
something like:
foreach function_that_has_site_ as coolfunc
if coolfunc(blabla,yada) == true:
return coolfunc(blabla,yada)
so it would go through them all until it gets something that's true.
thanks!
The inspect module, already mentioned in other answers, is especially handy because you get to easily filter the names and values of objects you care about. inspect.getmembers takes two arguments: the object whose members you're exploring, and a predicate (a function returning bool) which will accept (return True for) only the objects you care about.
To get "the object that is this module" you need the following well-known idiom:
import sys
this_module = sys.modules[__name__]
In your predicate, you want to select only objects which are functions and have names that start with site_:
import inspect
def function_that_has_site(f):
return inspect.isfunction(f) and f.__name__.startswith('site_')
With these two items in hand, your loop becomes:
for n, coolfunc in inspect.getmembers(this_module, function_that_has_site):
result = coolfunc(blabla, yada)
if result: return result
I have also split the loop body so that each function is called only once (which both saves time and is a safer approach, avoiding possible side effects)... as well as rewording it in Python;-)
Have you tried using the inspect module?
http://docs.python.org/library/inspect.html
The following will return the methods:
inspect.getmembers
Then you could invoke with:
methodobjToInvoke = getattr(classObj, methodName)
methodobj("arguments")
This method goes through all properties of the current module and executes all functions it finds with a name starting with site_:
import sys
import types
for elm in dir():
f = getattr(sys.modules[__name__], elm)
if isinstance(f, types.FunctionType) and f.__name__[:5] == "site_":
f()
The function-type check is unnecessary if only functions are have names starting with site_.
def run():
for f_name, f in globals().iteritems():
if not f_name.startswith('site_'):
continue
x = f()
if x:
return x
It's best to use a decorator to enumerate the functions you care about:
_funcs = []
def enumfunc(func):
_funcs.append(func)
return func
#enumfunc
def a():
print 'foo'
#enumfunc
def b():
print 'bar'
#enumfunc
def c():
print 'baz'
if __name__ == '__main__':
for f in _funcs:
f()
Try dir(), globals() or locals(). Or inspect module (as mentioned above).
def site_foo():
pass
def site_bar():
pass
for name, f in globals().items():
if name.startswith("site_"):
print name, f()

Categories

Resources