问题
I am developing an Agent class for an evolutionary algorithm. I need to add a method to it that is generated from a string inherited from the parents. Here a minimal example
class Agent:
def __init__(self, s='\tif x > y:\n\t\treturn 1'):
self.f_template = f'def f(self, x,y):\n{s}'
I would like to have the method self.f(self, x,y)
having self.f_template
as a function body.
I know I could add it later doing:
A = Agent()
exec(A.f_template)
A.f = partial(f, A)
>>> A.f(3,2)
1
But is it possible to achieve the same during __init__()
and not after?
Simply doing the following raises NameError: name 'f' is not defined
class Agent:
def __init__(self, s='\tif x > y:\n\t\treturn 1'):
self.f_template = f'def f(self, x,y):\n{s}'
exec(self.f_template)
self.f = partial(f, self)
回答1:
This is because the Python compiler looks at all the l-values in a code block when determining which variables are local, and in this case, f
is not defined as an l-value
, so the compiler complains at compilation time rather than at run time. This is not an issue in REPL where every line is compiled separately.
You can instead use the locals()
dict to access a variable name that is produced dynamically:
class Agent:
def __init__(self, s='\tif x > y:\n\t\treturn 1'):
self.f_template = f'def f(self, x,y):\n{s}'
exec(self.f_template)
self.f = partial(locals()['f'], self)
来源:https://stackoverflow.com/questions/52579310/how-to-add-a-dynamic-method-encoded-in-a-string-during-class-initialization