How to add a dynamic method encoded in a string during class initialization?

自闭症网瘾萝莉.ら 提交于 2019-12-24 10:35:01

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!