2016-02-04 3 views
4

Я пытаюсь определить объект master, чей атрибут/метод decide можно вызывать с выражением ex, но оценка этого выражения откладывается до тех пор, пока какая-либо логика в decide не запросит его (и может даже не сделать этого). Так, в коде следующим образом:Могу ли я вызвать ленивую оценку выражения?

master.decide(ex) 

должна быть возможным для ex оставаться невычисленной, если логика в decide так говорит. В коде ex означает «произвольное выражение, предоставленное клиентом моей библиотеки». Это может быть так же просто, как 1 + 2 (где я бы не заботился о ленивой оценке) до такого сложного, как do_http_request().delete_record_from_database() (где я, конечно, do уход).

Возможно ли такое? Я гибкий на стороне синтаксиса, поэтому, если существует решение, которое должно включать дополнительные операторы и т. Д. околоex, я могу это рассмотреть. Но я бы хотел, чтобы ex оставался выражением.

Я думал о (ab) с помощью коротких замыкающих операторов, таких как and и or, но, похоже, не существует способа заставить их вернуть что-то иное, чем логическое значение.

Лучшее, что я мог придумать оборачивает ex в лямбда:

master.decide(lambda: ex) 

def decide(ex): 
    if decide_to_do_it(): 
    result = ex() 
    somehow_use(result) 

Или передать его в виде строки и с помощью eval:

master.decide('ex') 

def decide(ex): 
    if decide_to_do_it(): 
    result = eval(ex) 
    somehow_use(result) 

(Да, это один будет иметь область видимости вопросы).

Возможно, есть волшебная функция, трюк или что-то еще, что позволило бы мне сохранить ex в качестве простого выражения?

+0

Проверить эту ссылку: http://stevenloria.com/lazy-evaluated-properties-in-python/ и это один http://stackoverflow.com/questions/5295038/python-lazy-evaluator –

+0

Это непонятно, что такое 'ex' в ваших поисках. Является ли это запрограммированной ранее функцией? Пользовательская строка для оценки? В первом ase вам не нужна лямбда, вы можете просто вызвать 'master.decide (ex)', функции python - объекты, которые вы можете передать в качестве аргументов. – DainDwarf

+0

@DainDwarf Пробовал уточнить – Angew

ответ

4

Вы можете определить coroutine с помощью yield здесь

def decide(): 
    ex=yield() 
    if ex: 
    result = ex() 
    somehow_use(result) 

master=decide() 
next(master) 
master.send(ex1) 
master.send(ex2) 
+0

Предположим, что клиент хочет 'ex' формы' insert_record_into_database() '.Не могли бы вы объяснить, как это предотвратит преждевременное оценивание такого выражения? – Angew

+0

@ После первого вызова 'next' программа будет продолжать ждать на' ex = yield() 'и будет двигаться вперед только тогда, когда u выполняет операцию' send'. После этого программа снова будет ждать, пока вы не сделаете другой 'send'. Я предполагаю, что это то, что вы хотите. Вы можете настроить его по мере необходимости. – vks

+0

Из того, что я понимаю, всегда будет оцениваться' ex', когда клиент отправит его. Это то, что я пытаюсь предотвратить. Наверное, нет никакого способа. – Angew

2

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

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

Это совершенно нормальный способ сделать это.

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