On Aug 27, 2015, at 08:22 PM, Max Brustkern wrote: >> @@ -39,8 +40,7 @@ >> """Must return a backend when called with a single backend.""" >> class Backend(object): >> pass >> - _create_backend = lambda: Backend() >> - backend = _pick_backend(dict(foo=_create_backend), '') >> + backend = _pick_backend(dict(foo=Backend), '') > >I'm not quite a clever in python as everyone else here, so I just want to >make sure that Backend is wanted here and not Backend() This seems to apply >to most of the tests around this, so I imagine they'd be breaking if it were >incorrect, I just like to be sure it's intentional. It is! lambdas are defined here: https://docs.python.org/3/reference/expressions.html#lambda The example given provides a great way to think about them. lambda args: expression is equivalent to def (args): return expression where the function is anonymous, i.e. it performs no name binding in the current namespace. When you assign the `lambda: Backend()` to _create_backend, it's the assignment that does the name binding to the function object, so its exactly equivalent to: def _create_backend(): return Backend() Note too that when _pick_backend() is called, the code is passing in a dictionary that maps the `foo` key to the *function object* created by the lambda; specifically, the calling of the lambda-created function object is deferred. It's exactly equivalent to just setting `foo` to the Backend function object without calling it. So in this case, the lambda is really just creating an unnecessary extra level of call. That's not quite the case where some of the lambdas take an argument, but you can see how the translation to explicit function definitions should generally go. One thing to keep in mind about my translations. To be accurate, the lambda-to-def conversion should return the value of the last expression, but I don't do this in all cases because the tests appear to only care that an exception is raised. Thus, the return values are mostly ignored. But for correctness, you could return the values out of the locally defined functions. BTW, this equivalence is the reason why lambda are generally frowned upon. They're almost never needed, and the savings in lines of code are usually not worth the cost in readability or comprehension. It was probably the fans of functional programming that tipped the balance against just removing them from Python 3. ;) >> === modified file 'setup.py' >> --- setup.py 2015-08-19 00:25:00 +0000 >> +++ setup.py 2015-08-24 19:50:50 +0000 >> @@ -20,9 +20,16 @@ >> from setuptools import find_packages, setup, Extension >> >> import sys >> + >> +from setuptools import find_packages, setup, Extension > >It surprises me that these are needed and haven't been included >previously. Was there something causing static analysis to not pick this up >before? Oh, that's weird. I don't remember adding that. Maybe it's a merge snafu? P.S. you can play with this to see the equivalence in action: def runme(func): print(func()) def hey(): return 'hey' yo = lambda: hey() def sup(): return hey() runme(hey) runme(yo) runme(sup) % python3 foo.py hey hey hey