14

Can I call a function nested inside another function from the global scope in python3.2?

def func1():
    def func2():
        print("Hello")
        return
    return

Is ther a way to call func2() from outside func1()?

4
  • 1
    You're generating the func2() object only if func1() is called first. For the sake of decoupling these tightly bound def statements, I recommend always defining each function individually, then calling func1() as a wrapper around func2().
    – yurisich
    Commented Dec 10, 2011 at 16:13
  • 3
    @Sam What is the motivation ??
    – eyquem
    Commented Dec 10, 2011 at 16:54
  • eyquem's answer works. It may not be elegant or recommended, but if you know what you are doing, you can use it. Much better than using the dunder attributes/methods etc.
    – sureshvv
    Commented Aug 25, 2017 at 17:58
  • programiz.com/python-programming/closure Commented Aug 25, 2017 at 19:12

4 Answers 4

23

No, unless you return the function:

def func1():
    def func2():
        print("Hello")
    return func2

innerfunc = func1()
innerfunc()

or even

func1()()
11

You want to use @larsmans' solution, but theoretically you can cut yourself into the code object of the locally accessible func1 and slice out the code object of func2 and execute that:

#!/usr/bin/env python

def func1():
    def func2():
        print("Hello")

# => co_consts is a tuple containing the literals used by the bytecode
print(func1.__code__.co_consts)
# => (None, <code object func2 at 0x100430c60, file "/tmp/8457669.py", line 4>)

exec(func1.__code__.co_consts[1])
# => prints 'Hello'

But again, this is nothing for production code.

Note: For a Python 2 version replace __code__ with func_code (and import the print_function from the __future__).

Some further reading:

2
  • 5
    +1 for sheer madness and audacity. While not fit for code you'll have to maintain, it's great to understand what happens under the hood (e.g. that functions are decoupled from their bytecode and that bytecode can be executed seperately).
    – user395760
    Commented Dec 10, 2011 at 16:25
  • 1
    @delnan " it's great to understand what happens under the hood" Yes !
    – eyquem
    Commented Dec 10, 2011 at 16:40
0

This is based on eyquem's solution.

def func1():
    global func2  # put it in global scope
    def func2():
        print("Hello")

Now you can invoke func2 directly.

But func1() would have to be called before you can call func2() otherwise it will not have been defined yet.

0
def func1():
    def func2():
        global fudu
        fudu = func2
        print("Hello")
    func2()


func1()

fudu()

print 'fudu' in dir()
print 'func2' in dir()

result

Hello
Hello
True
False

Also:

def func1():
    global func2
    def func2():
        print("Hello")
    func2()


func1()

print 'func2' in dir()
func2()

result

Hello
True
Hello

What's the interest?

5
  • 2
    I think the reason your answer has been downvoted is that you put in lots of code with little explanation, and because your code is something of a hack, and because there is a good solution using functional programming techniques. Commented Dec 12, 2011 at 18:14
  • @Kazark Thank you. I wasn't aware of this impression given by a lack of explanation. On the contrary, I thought that it could be lighter for a reader not to have evident comments concerning so easy to understand codes. - "hack" appears to me as an excessive word for my codes - I didn't try to give a better answer than other ones, I showed other ways that may give to OP additional ideas and comprehension.
    – eyquem
    Commented Dec 12, 2011 at 19:59
  • Okay, sorry for just calling it a hack; I should explain. Your code calls the inside function at definition, which is not called for in the spec. Also, the use of the global keyword could cause some people to frown on it. Commented Dec 12, 2011 at 20:32
  • This solution worked for me. It should not have been downvoted. Plus it should be the correct answer which is currently "No, you cannot do that".
    – sureshvv
    Commented Aug 25, 2017 at 17:52
  • @KeithPinson: In my case, I cannot return the inner function because it (the outer function) is already returning something. So it is not a good solution. eyquem's solution was perfect for my needs.
    – sureshvv
    Commented Aug 25, 2017 at 18:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.