почему я сталкиваюсь с проблемой, когда я собираюсь передать динамическую функцию в Python - PullRequest
0 голосов
/ 21 октября 2018

Я собираюсь передать функцию динамически другому классу, как показано ниже

    class simulator(object):
        def __init__(self, fn_):

            print(self.test(fn_))


        def test(self, fn):
            return  fn(self, 20)


    class t(object):

        s = 'def get_fitness(x, y):\n return x+y'

        exec(s)

        def fnGetFitness(self,genes):
            return get_fitness(genes, 10)

        simulator(fnGetFitness)



    t()

, но я сталкиваюсь с ошибкой ниже:

    File "N:/Job/GA/mine/dyn.py", line 25, in fnGetFitness
          return get_fitness(genes, 10)

    NameError: name 'get_fitness' is not defined

Я думаю, что-то связано с областями видимости, ноя не могу с этим справиться ни у кого?

РЕДАКТИРОВАТЬ:

это более простой код, показывающий проблему:

    class t(object):
        def __init__(self):
            exec('def get_fitness(x, y):\n return x+y')
            print(get_fitness(2,3))
    t()

1 Ответ

0 голосов
/ 21 октября 2018

не имеет ничего общего с exec.То, что вы делаете, эквивалентно (без безопасности):

class t(object):
    def get_fitness(x,y):
        return x+y

, но определение вашего метода находится на уровне класса, а не на simulator классе.

simulator(fnGetFitness)вызывает fnGetFitness из t контекста класса, поэтому он не знает вашей новой функции.

Это не может работать (также get_fitness должен быть оформлен как @staticmethod, потому что он не имеетself параметр)

То, что работает, - это динамическое (или нет) определение функции на уровне global , чтобы класс мог вызывать ее

s = 'def get_fitness(x, y):\n return x+y'
exec(s)

class t(object):
    def fnGetFitness(self,genes):
        return get_fitness(genes, 10)

    simulator(fnGetFitness)

t()

, которая исправила ее,но, честно говоря, я озадачен целью (мне уже понадобилось время, чтобы понять, как заставить что-то работать из вашего кода)

РЕДАКТИРОВАТЬ: был написан более простой и несколько другой (и связанный exec) кодОпубликовано в комментариях:

class t(object):
    def __init__(self):
        exec('def get_fitness(x, y):\n return x+y')
        print(get_fitness(2,3))
t()

это повышает NameError: name 'get_fitness' is not defined

сейчас это связано с exec.Когда __init__ анализируется, get_fitness не известен, потому что синтаксический анализатор не видел его как локальную переменную, даже если во время выполнения он установлен в словаре locals() как exec (связанный: почему 'ord' здесь рассматривается как неназначенная переменная? ).

Обходной путь - извлечь функцию из локальных переменных следующим образом:

class t(object):
    def __init__(self):
        exec('def get_fitness(x, y):\n return x+y')
        print(locals()["get_fitness"](2,3))

t()

thisработы и гравюры 5.

...