RE Python non segue questo principio. Generalmente, segue il principio. Esempio di base:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
Tuttavia, Python definisce espressioni e dichiarazioni separatamente. Poiché if
filiali, while
cicli, assegnazione distruttiva e altre istruzioni non possono essere usate in lambda
espressioni, la lettera del principio di Tennent non si applica a loro. Anche così, limitarsi a usare solo le espressioni Python produce ancora un sistema completo di Turing. Quindi non vedo questo come una violazione del principio; o meglio, se viola il principio, allora nessun linguaggio che definisce le dichiarazioni e le espressioni separatamente può eventualmente conformarsi al principio.
Inoltre, se il corpo dell'espressione lambda
catturasse una traccia di stack o eseguisse un'altra introspezione nella VM, ciò potrebbe causare differenze. Ma a mio avviso questo non dovrebbe essere considerato una violazione. Se expr
e (lambda: expr)()
necessariamente compili allo stesso bytecode, allora il principio riguarda davvero i compilatori non la semantica; ma se possono compilare un bytecode diverso, non ci si deve aspettare che lo stato VM sia identico in ciascun caso.
Una sorpresa può essere incontrata usando la sintassi di comprensione, anche se credo che questa non sia una violazione del principio di Tennent. Esempio:
>>> [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]
La sorpresa è il risultato di come vengono definite le liste di comprensione. La sopra comprensione 'sorpresa' è equivalente a questo codice:
>>> 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]
Visto in questo modo, la comprensione "sorpresa" di cui sopra è meno sorprendente, e non una violazione del principio di Tennent.