Избегайте или задерживайте оценку вещей, которые не могут быть использованы

Как это можно сделать элегантно в питоне? Это называется ленивой оценкой или я смешиваю название с чем-то еще? Например:

>>> def foo(x): ... print x ... return x ... >>> random.choice((foo('spam'), foo('eggs'))) spam eggs 'eggs' 

Но нам не нужно было оценивать все эти предметы или мы?

Это работает, но я считаю это довольно уродливым:

 >>> random.choice((lambda: foo('spam'), lambda: foo('eggs')))() eggs 'eggs' 

Другим примером может быть использование dict.get(key, somedefault()) где somedefault действительно не нужно было вызывать, если key not in dict .

5 Solutions collect form web for “Избегайте или задерживайте оценку вещей, которые не могут быть использованы”

Вы можете использовать partial (-приложенную функцию):

 import random def foo(x): print x return x from functools import partial print random.choice((partial(foo,'spam'), partial(foo,'eggs')))() 

Когда вам нужен диктофон с настройками по умолчанию, вы можете использовать defaultdict

 from collections import defaultdict d = defaultdict(somedefault) print d[k] # calls somedefault() when the key is missing 

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

Стандартный способ ленивой оценки в Python – использование генераторов .

 def foo(x): print x yield x random.choice((foo('spam'), foo('eggs'))).next() 

КСТАТИ. Python также допускает генераторные выражения , поэтому строка ниже не будет вычислять что-либо:

 g = (10**x for x in xrange(100000000)) 

Если вы не используете более реалистичный пример, я бы сделал это следующим образом:

 >>> def foo(x): ... print x ... return x ... >>> foo(random.choice(("spam", "eggs"))) spam 'spam' 

Но вы можете создать вспомогательный класс следующим образом:

 class LazyEval(object): def __init__(self, func, *args, **kwargs): self.func = func self.args = args self.kwargs = kwargs def __call__(self): return self.func(*self.args, **self.kwargs) random.choice((LazyEval(foo, "spam"), LazyEval(foo, "eggs")))() 

Просто сделайте это ленивым:

 random.choice((lambda: foo('spam'), lambda: foo('eggs')))() 

Другим решением является создание и возврат вызываемого объекта, который инкапсулирует действия, которые вы хотите выполнить при случайном выборе.

 def foo(sequence): def chooser(): choice = random.choice(sequence) print choice return choice return chooser >>> c = foo(['spam', 'eggs', 'ham']) >>> c() ... ham >>> 'ham' 
Python - лучший язык программирования в мире.