Dynamically adding method/state to a class/instance with name/value determined at runtime


April 2019


19 time


I need to dynamically add a class method with a name determined at runtime, and also an internal state that is determined at runtime. Here is the simplest example I can cook up:

class foo():

def h(self):   # h() is just a placeholder until we can do setattr()
    state = 'none'
    return state


print(dir(foo))         # includes 'bar'
print(dir(foo.bar))     # includes 'state'
print(getattr(foo.bar,'state')) # 'something'

f = foo()
print(getattr(f.bar,'state'))    # 'something'

# all is well up to here, but now we go awry
print(f.bar())   # 'none'

In the last line, the bar() return statement seems to be bound to the original definition in h() rather than its new context in foo. I have tried numerous things, and looked at introspection and other topics in stack overflow, but come up empty. How can I modify this code so that the last line yields 'something'?

1 answers


You are confusing the local variable state inside h, which has nothing to do with the attribute on the function object, h.state. They are not related... Note, f.bar.state will give you 'something'.

You could could do something like this:

In [6]: class Foo: pass

In [7]: def h(self):
   ...:     return self.state

In [8]: Foo.bar = h

In [9]: f = Foo()

In [10]: f.state = 'something'

In [11]: f.bar()
Out[11]: 'something'