RE Python ne suit pas ce principe. Généralement, il suit le principe. Exemple de base:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
Cependant, Python définit les expressions et les instructions séparément. Étant donné que les if
branches, les while
boucles, les affectations destructives et d'autres instructions ne peuvent pas du tout être utilisées dans les lambda
expressions, la lettre du principe Tennent ne s'applique pas à elles. Même ainsi, se limiter à utiliser uniquement des expressions Python produit toujours un système complet de Turing. Je ne considère donc pas cela comme une violation du principe; ou plutôt, s'il viole le principe, aucun langage définissant séparément les déclarations et les expressions ne peut être conforme au principe.
De plus, si le corps de l' lambda
expression capturait une trace de pile ou effectuait une autre introspection dans la machine virtuelle, cela pourrait provoquer des différences. Mais à mon avis, cela ne devrait pas être considéré comme une violation. Si expr
et (lambda: expr)()
nécessairement compiler dans le même bytecode, alors le principe concerne vraiment les compilateurs et non la sémantique; mais s'ils peuvent être compilés en différents octets, nous ne devons pas nous attendre à ce que l'état de la machine virtuelle soit identique dans chaque cas.
Une surprise peut être rencontrée en utilisant la syntaxe de compréhension, bien que je pense que ce n'est pas non plus une violation du principe Tennent. Exemple:
>>> [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 surprise est le résultat de la définition des compréhensions de liste. La compréhension «surprise» ci-dessus est équivalente à ce code:
>>> 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]
Vu de cette façon, la compréhension «surprise» ci-dessus est moins surprenante et ne constitue pas une violation du principe Tennent.