RE Python não segue este princípio. Geralmente, segue o princípio. Exemplo básico:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
No entanto, o Python define expressões e instruções separadamente. Como if
ramificações, while
loops, designações destrutivas e outras declarações não podem ser usadas em lambda
expressões, a letra do princípio de Tennent não se aplica a elas. Mesmo assim, restringir-se a usar apenas expressões Python ainda produz um sistema completo de Turing. Portanto, não vejo isso como uma violação do princípio; ou melhor, se violar o princípio, nenhuma linguagem que defina afirmações e expressões separadamente poderá estar em conformidade com o princípio.
Além disso, se o corpo da lambda
expressão estivesse capturando um rastreamento de pilha ou realizando outra introspecção na VM, isso poderia causar diferenças. Mas, na minha opinião, isso não deve ser considerado uma violação. Se expr
e (lambda: expr)()
necessariamente compilar no mesmo bytecode, o princípio realmente diz respeito aos compiladores, não à semântica; mas se eles puderem compilar em diferentes códigos de bytes, não devemos esperar que o estado da VM seja idêntico em cada caso.
Uma surpresa pode ser encontrada usando a sintaxe de compreensão, embora eu acredite que isso também não seja uma violação do princípio de Tennent. Exemplo:
>>> [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]
A surpresa é o resultado de como as compreensões da lista são definidas. A compreensão "surpresa" acima é equivalente a este código:
>>> 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 dessa maneira, a compreensão da "surpresa" acima é menos surpreendente, e não uma violação do princípio de Tennent.