Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - how can I dynamically create a function with a name based on a string read in from a file?

Let's say I have a file containing the string "unpredictable_words". I would like to read in this string and then define a function as follows:

def test_unpredictable_words(self):
    do_important_stuff()

I would then like to inject this function into a class definition so that this function can be called on any instances of this class.

How can I accomplish this?

I looked a bit at this answer - https://stackoverflow.com/a/8160676/1701170 - but I don't think it does what I want, exactly, or at least I can't understand what is going on.

like image 610
tadasajon Avatar asked Feb 19 '23 00:02

tadasajon


2 Answers

Python 2.7.3 (default, Sep 26 2012, 21:51:14) 
>>> def injected(self):
...     print 'injected'
... 
>>> class A(object):
...     pass
... 
>>> A.injected = injected
>>> a = A()
>>> a.injected()
injected
>>> def func2(self):
...     print 'func2'
... 
>>> setattr(A, 'injected2', func2)
>>> a.injected2()
func2
>>> 
like image 159
warvariuc Avatar answered Feb 20 '23 14:02

warvariuc


You don't need to define a function under one true name. Functions are first-class entitiens, you can pass them around and assign to variables. On top level, you use globals(), withing another function, locals() to bind a name:

>>> def foo(x):
...   return x + 1
... 
>>> name = 'unpredictable_words'
>>> 
>>> globals()['test_' + name] = foo
>>> 
>>> test_unpredictable_words(1)
2
>>> 
>>> def some_function():
...   locals()['test_' + name] = foo
...   return test_unpredictable_words(1)
... 
>>> some_function()
2
>>> 

Sometimes you still want that the function knows its name, in order to appear nicely in a stacktrace. Now test_unpredictable_words appear as foo in error messages. This is not easy to fix, since that name is stored in foo.func_code.co_name and can't be changed.

like image 37
9000 Avatar answered Feb 20 '23 15:02

9000