Как добавить динамический метод, закодированный в строку во время инициализации класса? - PullRequest
0 голосов
/ 30 сентября 2018

Я занимаюсь разработкой класса агента для эволюционного алгоритма.Мне нужно добавить метод, который генерируется из строки, унаследованной от родителей.Вот минимальный пример

class Agent:
    def __init__(self, s='\tif x > y:\n\t\treturn 1'):
        self.f_template = f'def f(self, x,y):\n{s}'

Я хотел бы иметь метод self.f(self, x,y) с self.f_template в качестве тела функции.Я знаю, что мог бы добавить это позже, выполнив:

A = Agent()
exec(A.f_template)
A.f = partial(f, A)

>>> A.f(3,2)
1

Но возможно ли добиться того же во время __init__(), а не после?

Простое выполнение следующих рейзов 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 Ответ

0 голосов
/ 30 сентября 2018

Это потому, что компилятор Python просматривает все l-значения в блоке кода при определении того, какие переменные являются локальными, и в этом случае f не определяется как l-value, поэтому компилятор жалуется на компиляциювремя, а не во время выполнения.Это не проблема в REPL, где каждая строка компилируется отдельно.

Вместо этого можно использовать диктовку locals() для доступа к имени переменной, которое создается динамически:

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)
...