This is true, as scoping, searching and closing names are defined in Python.
Python introduces new bindings in the namespace through assignment and function parameter lists. i therefore not defined in the lambda namespace, but in the __init__() namespace. The search for the name i in lambda, therefore, ends in the __init__() namespace, where i bound to 9 . This is called a "close".
You can get around this admittedly non-intuitive (but well-defined) semantics by passing i as a keyword argument with a default value. As said, the names in the parameter lists introduce new bindings in the local namespace, so the i inside lambda becomes independent of the i in .__init__() :
self._numberButtons[i].clicked.connect(lambda i=i: self._number(i))
A more readable, less magical alternative is functools.partial :
self._numberButtons[i].clicked.connect(partial(self._number, i))
I use the new signal and slot syntax here just for convenience, the old style syntax works the same.
lunaryorn
source share