嵌套函数的实际示例

11 投票
8 回答
5924 浏览
提问于 2025-04-15 17:43

我之前问过关于嵌套函数是怎么回事,但遗憾的是我还是不太明白。为了更好地理解,有人能给我一些嵌套函数在实际中使用的例子吗?

非常感谢!

8 个回答

4

嵌套函数可以避免在程序的其他地方出现一些只在特定地方有意义的函数和变量,这样可以让代码看起来更整洁。

比如,我们可以这样定义一个用来返回斐波那契数列的函数:

>>> def fib(n):
        def rec():
            return fib(n-1) + fib(n-2)

        if n == 0:
            return 0
        elif n == 1:
            return 1
        else:
            return rec()

>>> map(fib, range(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

补充一下:实际上,使用生成器会是一个更好的解决方案,但这个例子主要是为了展示如何利用嵌套函数。

9

装饰器是一种非常流行的使用嵌套函数的方法。下面是一个装饰器的例子,它会在调用被装饰的函数之前和之后打印一条信息。

def entry_exit(f):
    def new_f(*args, **kwargs):
        print "Entering", f.__name__
        f(*args, **kwargs)
        print "Exited", f.__name__
    return new_f

@entry_exit
def func1():
    print "inside func1()"

@entry_exit
def func2():
    print "inside func2()"

func1()
func2()
print func1.__name__
10

你的问题让我很好奇,于是我去查看了一些实际的代码:Python的标准库。我发现了67个嵌套函数的例子。下面是几个例子,并附上简单的解释。

使用嵌套函数的一个非常简单的原因是,你定义的函数不需要是全局的,因为只有外层的函数会用到它。这里有一个来自Python的quopri.py标准库模块的典型例子:

def encode(input, output, quotetabs, header = 0):
    ...
    def write(s, output=output, lineEnd='\n'):
        # RFC 1521 requires that the line ending in a space or tab must have
        # that trailing character encoded.
        if s and s[-1:] in ' \t':
            output.write(s[:-1] + quote(s[-1]) + lineEnd)
        elif s == '.':
            output.write(quote(s) + lineEnd)
        else:
            output.write(s + lineEnd)

    ...  # 35 more lines of code that call write in several places

在这里,encode函数中有一些公共代码,所以作者把它提取出来,放到了一个叫write的函数里。


嵌套函数的另一个常见用法是re.sub。以下是来自json/encode.py标准库模块的一段代码:

def encode_basestring(s):
    """Return a JSON representation of a Python string

    """
    def replace(match):
        return ESCAPE_DCT[match.group(0)]
    return '"' + ESCAPE.sub(replace, s) + '"'

这里的ESCAPE是一个正则表达式,ESCAPE.sub(replace, s)会在字符串s中找到所有匹配ESCAPE的部分,并用replace(match)替换每一个匹配项。


实际上,任何接受函数作为参数的API,比如re.sub,都可能出现嵌套函数很方便的情况。例如,在turtle.py中,有一些简单的演示代码是这样写的:

    def baba(xdummy, ydummy):
        clearscreen()
        bye()

    ...
    tri.write("  Click me!", font = ("Courier", 12, "bold") )
    tri.onclick(baba, 1)

onclick期望你传入一个事件处理函数,所以我们定义了一个并把它传了进去。

撰写回答