how to dynamically create class methods ?

Arnaud Delobelle arnodel at googlemail.com
Wed Mar 26 03:55:22 EDT 2008


On Mar 25, 10:55 pm, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:

[...]

In my haste I forgot to finish my post:

> Here's an example that might help.
>
> class MyClass(object):
>     pass
>
> records = ["spam", "ham"]
> for record in records:
>     # define a new function
>     def f(n):
>         return (record + " ")*n
>     # create a new instance
>     instance = MyClass()
>     # and dynamically add a method to it
>     setattr(instance, 'execute', f)
>     instance.execute(5)

Except it only *appears* to work.  What happens if were store the
instances in a list and then execute them all in one go?

class MyClass(object):
    pass

records = ["spam", "ham"]
instances = []
for record in records:
    # define a new function
    def f(n):
        return (record + " ")*n
    # create a new instance
    instance = MyClass()
    # and dynamically add a method to it
    setattr(instance, 'execute', f)
    instances.append(instance) # ONLY THIS LINE CHANGED

for instance in instances:
    instance.execute(5)

Outputs:
'ham ham ham ham ham '
'ham ham ham ham ham '

Because the name 'record' in f is bound to 'ham' after the loop.

To fix this, you can for example change

    def f(n): ...

to

    def f(n, record=record): ...

This way, 'record' is local to f and won't change at the next
iteration of the loop.

--
Arnaud




More information about the Python-list mailing list