0

Possible Duplicate:
Local variables in Python nested functions

Here is my problem, I need to create functions dynamically in python. I have a list in parameter and I need to create a function for each element of this list.

Here is an example :

list_func = []
list_param = ['foo','bar']

for param in list_param:
    def print_func():
        print(param)

    list_func += [print_func]

for func in list_func:
    func()

with this code the second loop will just print the last parameter. Here is the output :

bar
bar

I need

foo
bar

Thanks

Community
  • 1
  • 1
IxDay
  • 3,667
  • 2
  • 22
  • 27

4 Answers4

2

Use functools.partial for this.

>>> import functools
>>> def print_func(param):
...     print(param)
...     
>>> list_func = [functools.partial(print_func, x) for x in ["foo", "bar"]]
>>> list_func[0]()
foo
>>> list_func[1]()
bar

Alternatively, you can define a callable class:

class Printer(object):
    def __init__(self, param):
        self.param = param

    def __call__(self):
        print(self.param)

then list_func = [Printer(x) for x in ["foo", "bar"]]. This might be a good idea when your function get complicated.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • Thank you for your help, I think the callable class is the cleanest solution for my issue. I can't use functool because my print_func can not have parameters. – IxDay Nov 16 '12 at 12:21
1

You can use lambda :

In [87]: list_func = []

In [88]: list_param = ['foo','bar']

In [89]: for param in list_param:
    list_func.append(lambda i=param:i)
   ....:     


In [91]: list_func[0]()
Out[91]: 'foo'

In [92]: list_func[1]()
Out[92]: 'bar'
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

I just modified you're code slightly:

list_func = []
list_param = ['foo','bar']

def make_print_func(param):
    def print_func():
        print(param)
    return print_func

list_func += [make_print_func(param) for param in list_param]

for func in list_func:
    func()

Now there is a function make_print_func that generates the functions that you need on the fly.

Output is this:

foo
bar
J. P. Petersen
  • 4,871
  • 4
  • 33
  • 33
  • Thank you for your reply, it is exactly what I need but the callable class from larsmans is maybe a bit cleaner. – IxDay Nov 16 '12 at 12:24
1
list_func = []
list_param = ['foo', 'bar']

for param in list_param:
    def print_func(arg=param): #Look at this string
        print(arg)

    list_func.append(print_func)

for func in list_func:
    func()
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
alexvassel
  • 10,600
  • 2
  • 29
  • 31