Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm not sure, why you think the value of the lambda function is thrown away. The lambda function returns a generator object. The function body of a generator is generally not executed until you call .next() on it, so that's why you don't get a NameError instantly. Also the value, that you .send() into the generator is not thrown away either. In your example the generator just runs into an exception before it goes into a state in which it would accept a .send() call. Just consider this modified example:

  >>> f=lambda: (yield)
  >>> gen=f()
  >>> gen.next()
  >>> gen.send('foobar')
  'foobar'


I think you misunderstood which value gets thrown away.

Consider this:

    >>> g = lambda x: 7
    >>> f = lambda: g((yield))
    >>> list(f())
    [None]
Can you tell me where the 7 went to? As far as I see, it went into oblivion.


Strange. With Python 2.6 I get [None, 7] while with Python 2.7 it is [None]. Looking at the OP codes the 2.7 one's look weird.

Python 2.6:

  >>> dis.dis(f)
    1           0 LOAD_GLOBAL              0 (g)
                3 LOAD_CONST               0 (None)
                6 YIELD_VALUE
                7 CALL_FUNCTION            1
               10 RETURN_VALUE
Python 2.7:

  >>> dis.dis(f)
    1           0 LOAD_GLOBAL              0 (g)
                3 LOAD_CONST               0 (None)
                6 YIELD_VALUE
                7 CALL_FUNCTION            1
               10 POP_TOP
               11 LOAD_CONST               0 (None)
               14 RETURN_VALUE
In essence the Python 2.7 compiler decides to throw away the result of the g() function call and replaces it with None. Does anyone understand why?



Ahh, thanks!


As i said, f() returns a generator object in this case. So you're calling list on a generator that yields None once, the result of which is a list that contains None. If you change the `yield` to `yield "foobar"`, list(f()) will get you `["foobar"]`.

Edit: Perhaps, to clear things up more, about where the value 7 went- your snippet can be expressed without using lambdas as

  >>> def g(x):
  ...  return 7
  ... 
  >>> def f():
  ...  v = (yield)
  ...  g(v)
  ... 
  >>> list(f())
  [None]
Note that there's no return before g(v) because generators (at least in 2.7) can only yield, not return a value.


I'm thinking that the parent is expecting 'yield' to return 'None' into g(), and then for g() to return 7 since it doesn't do anything with the 'x' parameter, and is confused why that isn't the case.


Yes, but I think this is cleared up if you consider that calling a generator function does not execute its body, but return generator object. It doesn't really matter if it's a lambda or a regular named function.


Sure, I understand all of that. I'm just saying it's unusual to see a lambda function throwing away the value like that.


The value of the lambda is the generator object. How else could you call list() on it if it was thrown away?


You're just using the word "value" in a different way. I meant "value" as in the 7.


You're right. I am still referring to that particular part of your blog post:

  >> So that’s the only case I can think of where Python
  >> completely throws away the value of a lambda function.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: