Buttons840
Buttons840

Reputation: 9637

Lambdas, callable class instances, and scoping; why doesn't it work in Python 2.7?

Can someone explain to me why the following code produces the exception it does?

>>> class CallableKlass(object):
    def __init__(self, callible):
        self.callible = callible
    def __call__(self, arg):
        return self.callible(arg)


>>> class Klass(object):
    d = {'foo': 'bar'}
    m = CallableKlass(lambda x: d[x])


>>> Klass.m('foo')

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    Klass.m('foo')
  File "<pyshell#5>", line 5, in __call__
    return self.callible(arg)
  File "<pyshell#9>", line 3, in <lambda>
    m = CallableKlass(lambda x: d[x])
NameError: global name 'd' is not defined

Upvotes: 4

Views: 123

Answers (2)

BrenBarn
BrenBarn

Reputation: 251488

The class namespace (stuff defined directly in the class body) is not accessible from within functions defined in that namespace. A lambda is just a function, so this applies to lambdas as well. Your CallableKlass is a red herring. The behavior is the same in this simpler case:

>>> class Foo(object):
...     d = {'foo': 'bar'}
...     (lambda stuff: d[stuff])('foo')
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    class Foo(object):
  File "<pyshell#3>", line 3, in Foo
    (lambda stuff: d[stuff])('foo')
  File "<pyshell#3>", line 3, in <lambda>
    (lambda stuff: d[stuff])('foo')
NameError: global name 'd' is not defined
>>> class Foo(object):
...     d = {'foo': 'bar'}
...     def f(stuff):
...         d[stuff]
...     f('foo')
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    class Foo(object):
  File "<pyshell#4>", line 5, in Foo
    f('foo')
  File "<pyshell#4>", line 4, in f
    d[stuff]
NameError: global name 'd' is not defined

Upvotes: 3

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251096

you should use Klass.d inside lambda, as the variables declared inside a class becomes attribute of that class. That's why your program raised that error, as it is not able to find anything like d in global variables.:

class Klass(object):
    d = {'foo': 'bar'}
    m = CallableKlass(lambda x: Klass.d[x])

Upvotes: 2

Related Questions