unexpected behaviour of lambda expression

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • leonhard.vogt@gmx.ch

    #1

    unexpected behaviour of lambda expression

    Please consider that example:
    Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)]
    on win32
    Type "help", "copyright" , "credits" or "license" for more information.
    >>s = 'foo'
    >>f = lambda x: s
    >>f(None)
    'foo'
    >>s = 'bar'
    >>f(None)
    'bar'
    >>del(s)
    >>f(None)
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 1, in <lambda>
    NameError: global name 's' is not defined

    It seems to me, that f is referencing the name s instead of the string
    object bound to it
    i would expect the analogous behaviour to the following example:
    Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)]
    on win32
    Type "help", "copyright" , "credits" or "license" for more information.
    >>s = 'foo'
    >>f = s
    >>f
    'foo'
    >>s = 'bar'
    >>f
    'foo'

    I could work around this but I am interested why there is that
    difference.
    Leonhard

  • Fredrik Lundh

    #2
    Re: unexpected behaviour of lambda expression

    leonhard.vogt@g mx.ch wrote:
    Please consider that example:
    Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)]
    on win32
    Type "help", "copyright" , "credits" or "license" for more information.
    >>>s = 'foo'
    >>>f = lambda x: s
    >>>f(None)
    'foo'
    >>>s = 'bar'
    >>>f(None)
    'bar'
    >>>del(s)
    >>>f(None)
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 1, in <lambda>
    NameError: global name 's' is not defined
    >
    It seems to me, that f is referencing the name s instead of the string
    object bound to it
    that's how lexical scoping works, of course.

    if you want to bind to the object instead of the name, use explicit binding:

    f = lambda x, s=s: s

    </F>



    Comment

    • Duncan Booth

      #3
      Re: unexpected behaviour of lambda expression

      leonhard.vogt@g mx.ch wrote:
      >>>f = lambda x: s
      ....
      >>>f(None)
      Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "<stdin>", line 1, in <lambda>
      NameError: global name 's' is not defined
      >
      It seems to me, that f is referencing the name s instead of the string
      object bound to it
      Of course it is. Why would you expect a function to lookup its global
      variables before it is called? Remember "f = lambda x: s" is just a
      confusing way to write:

      def f(x):
      return s

      Comment

      • leonhard.vogt@gmx.ch

        #4
        Re: unexpected behaviour of lambda expression

        Fredrik Lundh schrieb:
        leonhard.vogt@g mx.ch wrote:
        >
        Please consider that example:
        Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)]
        on win32
        Type "help", "copyright" , "credits" or "license" for more information.
        >>s = 'foo'
        >>f = lambda x: s
        >>f(None)
        'foo'
        >>s = 'bar'
        >>f(None)
        'bar'
        >>del(s)
        >>f(None)
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<stdin>", line 1, in <lambda>
        NameError: global name 's' is not defined

        It seems to me, that f is referencing the name s instead of the string
        object bound to it
        >
        that's how lexical scoping works, of course.
        >
        if you want to bind to the object instead of the name, use explicit binding:
        >
        f = lambda x, s=s: s
        >
        </F>
        Thank you, together with the response of Duncan it is clear to me now.
        I will use something like
        >>def makefunc(t):
        .... return lambda x: t
        ....
        >>s = 'foo'
        >>f = makefunc(s)
        >>f(None)
        'foo'
        >>s = 'bar'
        >>f(None)
        'foo'

        Leonhard

        Comment

        Working...