RE Python не следует этому принципу. Как правило, он следует принципу. Основной пример:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
Тем не менее, Python определяет выражения и операторы отдельно. Поскольку if
ветви, while
циклы, деструктивное присваивание и другие операторы вообще не могут использоваться в lambda
выражениях, буква принципа Теннента к ним не относится. Тем не менее, ограничиваясь использованием только выражений Python, все равно получается полная система Тьюринга. Поэтому я не считаю это нарушением принципа; или, скорее, если это нарушает принцип, то никакой язык, который определяет утверждения и выражения отдельно, не может соответствовать этому принципу.
Кроме того, если тело lambda
выражения захватывает трассировку стека или выполняет другой самоанализ в виртуальной машине, это может вызвать различия. Но, на мой взгляд, это не должно рассматриваться как нарушение. Если expr
и (lambda: expr)()
обязательно компилировать в один и тот же байт-код, то этот принцип действительно касается компиляторов, а не семантики; но если они могут компилироваться в другой байт-код, мы не должны ожидать, что состояние VM будет одинаковым в каждом случае.
При использовании синтаксиса понимания может возникнуть неожиданность, хотя я считаю, что это также не является нарушением принципа Теннента. Пример:
>>> [x for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [lambda: x for x in xrange(10)]] # surprise!
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>>> # application of Tennent principle to first expression
... [(lambda: x)() for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [(lambda x: lambda: x)(x) for x in xrange(10)]] # force-rebind x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> map(lambda f:f(), map(lambda x: lambda: x, xrange(10))) # no issue with this form
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Сюрприз - результат того, как определены списочные представления. Вышеупомянутое «неожиданное» понимание эквивалентно следующему коду:
>>> result = []
>>> for x in xrange(10):
... # the same, mutable, variable x is used each time
... result.append(lambda: x)
...
>>> r2 = []
>>> for f in result:
... r2.append(f())
...
>>> r2
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
При таком понимании «неожиданное» понимание выше не так удивительно и не является нарушением принципа Теннента.