Suppose I need to create 10 functions called add1, add2, ..., add10. For each i, addi takes in an integer x and outputs x+i.
Python gave me a NameError when I tried the following and evaluated add2(10).
for i in range(10):
def addi(x):
return x + (i+1)
I know the above code is wrong, since the addi functions I've defined aren't mutable; I'm pretty sure all I've done is redefine addi 10 times. How can these 10 functions be quickly defined?
Various combinations of methods can be used with multiple variables using for loop. Using zip () function with for loop for multiple variables. Using for loop with a key-value pair of a dictionary.
To loop over a dictionary and to get the values, Python has two in-built functions: items () – This function helps us get key-value pairs from the dictionary. values () – This function helps us get only values from the dictionary without the keys. In this example, we get the key-value pairs.
The range () Function To loop through a set of code a specified number of times, we can use the range () function, The range () function returns a sequence of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.
With the for loop we can execute a set of statements, once for each item in a list, tuple, set etc. The for loop does not require an indexing variable to set beforehand. Even strings are iterable objects, they contain a sequence of characters:
Use functools.partial
combined with a dictionary in this situation.
I assume what you really want to do is more complex, since multiple functions are not necessary for this specific task.
from functools import partial
def add(x, i):
return x + i
d = {f'add{k}': partial(add, i=k) for k in range(1, 10)}
d['add3'](5) # 8
Explanation
functools.partial
is a higher order function which returns an input function with selected argument(s) fixed.From the comments, a commonly asked question goes:
OP seems to be asking if there's a better way of just doing
def add1:
...def add2:
... While I agree with your solution, I don't agree with the fact that it's the solution to the current question. - MooingRawrWhy is using an iterator to define functions a bad idea? It seemed like a good way to shorten code to me. Is it generally better to define them one by one? – jessica
My short answer:
Using
globals().update
to pollute the namespace is a bad idea.. Hold related variables in specially made collections. It makes sense from any viewpoint (maintainability, calling, modifying, etc). – jpp
@BoarGules's extend answer:
It's not a good idea because it creates functions dynamically, but they can only be called by static code (otherwise the code wouldn't know what to call), so what's the point of them being dynamic? Creating them dynamically makes the code hard to read (you can't easily search for the function definition) and gives IDEs unnecessary trouble in their efforts to help you. You save tedious, repetitive coding, but programming sometimes entails tedious and careful repetition. The effort and skill would be better spent speeding up the coding (clever search/replace, macros, whatever). – BoarGules
Functions aren't mutable in general; but they may have references to data that is. In your snippet, this reference is a little unclear, but i
only occurs once in the function body, as a read. It therefore reads from some outer scope, typically the function or module your for
loop is contained within. Because this happens to be a shared context, every addi
function will end up with the same i
.
Another issue is that you're using the name addi
on every iteration, and the function never appeared under another name. So whatever addi
functions were defined earlier are lost. This leads us to the third question; why would you want to create names (such as function names) dynamically? It's almost always better to use a collection, such as the d
dictionary in jpp's answer. Otherwise, what code would even refer to the functions you created?
All that said, it is still possible to do what you asked for, albeit very strange. Here's one way:
def addfunc(n):
def addn(x):
return x+n
return addn
for i in range(1,10):
globals()['add{}'.format(i)] = addfunc(i)
This abuses globals
to inject dynamically created names into the module's namespace, and nests each of these functions within another to create the namespaces holding their individual n
values. Another classic hack was using a default argument, and partial application of operator.add
is a neater functional style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With