在一个函数中调用另一个函数的定义

12

我可以在Python 3.2的全局作用域中调用嵌套在另一个函数内部的函数吗?

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

是否有一种方法可以从func1()外部调用func2()?


1
只有在调用func1()函数时,才会生成func2()对象。为了解耦这些紧密绑定的def语句,我建议始终单独定义每个函数,然后使用func1()作为func2()的包装器进行调用。 - yurisich
3
@Sam 什么是动机? - eyquem
eyquem的答案可行。虽然可能不够优雅或推荐,但如果你知道自己在做什么,就可以使用它。比使用dunder属性/方法等要好得多。 - sureshvv
https://www.programiz.com/python-programming/closure - mortysporty
4个回答

23
不行,除非你返回该函数:
def func1():
    def func2():
        print("Hello")
    return func2

innerfunc = func1()
innerfunc()

甚至更多

func1()()

11

想要使用@larsmans'提供的解决方案,但理论上您可以将自己插入到本地可访问的func1代码对象中,并切片出func2的代码对象并执行它:

#!/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'

但是,这对于生产代码来说什么都不是。

注意:对于Python 2版本,请将__code__替换为func_code(并从__future__导入print_function)。

进一步阅读:


5
对于纯疯狂和大胆的做法,点一个赞。虽然不适合用于需要维护的代码,但理解发生在幕后的事情很有意义(例如函数与它们的字节码是分离的,字节码可以单独执行)。 - user395760
1
@delnan:“了解引擎内部发生的事情真是太好了!”是的! - eyquem

0
这是基于eyquem的解决方案。
def func1():
    global func2  # put it in global scope
    def func2():
        print("Hello")

现在你可以直接调用func2。

但是在调用func2()之前必须先调用func1(),否则它还没有被定义。


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


func1()

fudu()

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

结果

Hello
Hello
True
False

另外:

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


func1()

print 'func2' in dir()
func2()

结果

Hello
True
Hello

有什么兴趣?


2
我认为你的回答被投票反对的原因是你放置了很多没有解释的代码,而且你的代码有些像是一个hack,并且已经有一种使用函数式编程技巧的好的解决方案 - Keith Pinson
@Kazark 谢谢。我没有意识到缺乏解释会给人留下这样的印象。相反,我认为对于易于理解的代码来说,没有明显的注释可能会更轻松地阅读。对于我的代码来说,“hack”这个词对我来说有些过分了。我并没有试图给出比其他答案更好的答案,而是展示了其他可能给OP带来额外想法和理解的方法。 - eyquem
好的,抱歉之前只是称其为hack;我应该解释一下。你的代码在定义时调用了内部函数,这在规范中并没有要求。此外,使用global关键字可能会引起某些人的反感。 - Keith Pinson
这个解决方案对我很有效。它不应该被投票降低。而且它应该是正确的答案,目前是“不,你不能这样做”。 - sureshvv
@KeithPinson:在我的情况下,我无法返回内部函数,因为外部函数已经返回了某些内容。因此,这不是一个好的解决方案。eyquem的解决方案非常适合我的需求。 - sureshvv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接