2016-08-24 3 views
1

Я получаю с ума такого рода проблемы:итерационный определение функций в Python

У меня есть список строки, представляющие функции (Eval), мне нужно сначала заменить переменные с общим x[0], x[1],....

Некоторое время назад я обнаружил, что могу сделать это, используя subs(). Затем мне нужно сгенерировать список функций (чтобы определить ограничения в минимизации SciPy). Я пытаюсь что-то вроде:

el=[budget.v.values()[0],silly.v.values()[0]] # my list of string/equations 

fl=[] 
for i in range(len(el)): 
    def sos(v): 
     vdict = dict(zip(q.v.values(),v)) 
     return eval(el[i]).subs(vdict) 
    fl.append(sos) 
    del sos # this may be unnecessary 

Результат для фл является:

[<function sos at 0x19a26aa28>, <function sos at 0x199e3f398>] 

но две функции всегда один и тот же результат (что соответствует определению Страшного «SOS»). Как сохранить различные определения функций?

+0

_ "но две функции всегда дают одинаковый результат (соответствующий последнему определению sos)" _, потому что 'i' записывается по имени и поэтому, когда' sos() 'вызывается' i' будет иметь окончательное значение. См. [Здесь] (http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures) – FujiApple

ответ

2

Ваш комментарий:

но две функции всегда один и тот же результат (что соответствует определению Страшного «SOS»)

Это большой ключ, что вы, вероятно, работать в этом common gotcha!

Ваш код не находится в работоспособном виде, поэтому я не могу это подтвердить, но он явно имеет эту ошибку. Существуют различные способы исправить это, включая использование functools.partial, как описано в первой ссылке.

Например (непроверенные, как ваш код не является исполняемым, как есть):

import functools 

for i in range(len(el)): 
    def sos(i, v): 
     vdict = dict(zip(q.v.values(),v)) 
     return eval(el[i]).subs(vdict) 
    fl.append(functools.partial(sos, i)) 

Учитывая это, теперь вы можете реорганизовывать этот код, чтобы избежать переопределения функции внутри цикла:

def sos(i, v): 
    vdict = dict(zip([2], v)) 
    return eval(el[i]).subs(vdict) 

for i in range(len(el)): 
    fl.append(functools.partial(sos, i)) 

Чтобы дать Вам полную и работоспособный пример:

import functools 

def add_x(x, v): 
    return x + v 

add_5 = functools.partial(add_x, 5) 
print add_5(1) 

Производит:

6 
+0

Большое спасибо за подсказку! Я понял, что это связано с «поздним связыванием». Большая помощь! –

Смежные вопросы