2

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?

4
  • 1
    Functions are objects too; your writer() function returned one. Commented Mar 6, 2015 at 14:29
  • it is basically the same as nesting an inner function like in a function factory Commented Mar 6, 2015 at 14:32
  • Try typing one of these into the interactive interpreter to get a bit of insight into what's happening: writer() (don't assign it to anything, thus forcing what it returns to be printed to the console), or who. Commented Mar 6, 2015 at 14:33
  • read up on closures and functions as objects. also, more to your point, lambda just defines a function. when you return it, you can use it. Commented Mar 6, 2015 at 14:35

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

So the term closure refers to everything within an enclosing def func as long as we're returning a function (named or anonymous)?
Yes basically the outer function closes over the inner, if not there would no longer be a reference to e when it is called in the inner function so it would be as if you never defined it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.