b0bu
b0bu

Reputation: 1230

Python def function assignment with lambda

How does this work:

def writer():
    title = "Mr"
    name = (lambda x: title + ' ' + x)
    return name

writer("Bond")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: writer() takes 0 positional arguments but 1 was given

who = writer()

who("Bond")
'Mr Bond'

So lambda takes the positional argument x right? And by assigning the function object writer() to 'who' I somehow have access to lambda?

Upvotes: 2

Views: 1136

Answers (1)

Padraic Cunningham
Padraic Cunningham

Reputation: 180401

You are returning a function, the outer function closes over creating a closure with the __closure__ method so there is still a reference to title so it can be used in the inner function:

def writer():
    title = "Mr"
    name = (lambda x: title + ' ' + x)
    return name

wr = writer()
print(wr.__closure__)
print(wr("foo"))

def writer():
    title = "Mr"
    def name(x):
        return title + ' ' + x
    return name

wr = writer()
print(wr.__closure__)
print(wr("foo"))

(<cell at 0x7eff4b221588: str object at 0x7eff4b11a500>,)
Mr foo
(<cell at 0x7eff49883108: str object at 0x7eff4b11a500>,)
Mr foo

If you take the following function factory that takes an input e which is an exponent you want to raise x in the inner function to:

def exp(e):
    def rse_to(x):
        return x ** e
    return rse_to


square = exp(2) 

print(square(2)) # call inner function, returns  2 ** 2

In your first function, you don't take any argument so you cannot pass any args. You are simply returning the lambda function which takes one positional argument.

def writer():
    title = "Mr"
    name = (lambda x: title + ' ' + x)
    return name

wr = writer()
print(wr)
<function writer.<locals>.<lambda> at 0x7f60e699dbf8>

What you are trying to do by passing an arg to writer is no different to defining a normal function which takes no args and try to pass one to it.

In [2]: def foo():
   ...:     print("I take no args")
   ...:     

In [3]: foo()
I take no args

In [4]: foo(2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-3ab2f4e33a15> in <module>()
----> 1 foo(2)

TypeError: foo() takes 0 positional arguments but 1 was given

Upvotes: 2

Related Questions