C'est plus une curiosité que rien, mais je viens de remarquer ce qui suit. Si je suis la définition d'une auto-référentielle lambda, je peux le faire facilement:
>>> f = lambda: f
>>> f() is f
True
Mais si je suis la définition d'une auto-référentielle de la liste, je dois le faire en plus d'une instruction:
>>> a = [a]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> a = []
>>> a.append(a)
>>> a[0] is a
True
>>> a
[[...]]
J'ai aussi remarqué que ce n'est pas limité à des listes, mais semble comme toute autre expression autre qu'un lambda ne peut pas référencer la variable à gauche de l'affectation. Par exemple, si vous avez un cyclique de liste liée à un nœud, vous ne pouvez pas simplement aller:
>>> class Node(object):
... def __init__(self, next_node):
... self.next = next_node
...
>>> n = Node(n)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined
Au lieu de cela, vous devez le faire en deux états:
>>> n = Node(None)
>>> n.next = n
>>> n is n.next
True
Personne ne sait ce que la philosophie derrière cette différence est? Je comprends que récursive lambda sont utilisés beaucoup plus fréquemment, et donc de soutien à l'auto-référence est important pour les lambdas, mais pourquoi ne pas l'autoriser pour toute cession?
EDIT: Les réponses ci-dessous clarifier ce assez bien. La raison en est que les variables dans les expressions lambda en Python sont évalués à chaque fois le lambda est appelé, non pas lorsqu'il est défini. En ce sens, ils sont exactement comme les fonctions définies à l'aide de def
. J'ai écrit le code suivant à expérimenter avec la façon dont cela fonctionne, à la fois avec les lambdas et def
fonctions dans le cas où il pourrait aider à clarifier pour tout le monde.
>>> f = lambda: f
>>> f() is f
True
>>> g = f
>>> f = "something else"
>>> g()
'something else'
>>> f = "hello"
>>> g()
'hello'
>>> f = g
>>> g() is f
True
>>> def f():
... print(f)
...
>>> f()
<function f at 0x10d125560>
>>> g = f
>>> g()
<function f at 0x10d125560>
>>> f = "test"
>>> g()
test
>>> f = "something else"
>>> g()
something else