Python中的嵌套函数

Posted

技术标签:

【中文标题】Python中的嵌套函数【英文标题】:Nested Function in Python 【发布时间】:2010-12-08 00:36:44 【问题描述】:

我们可以使用这样的 Python 代码获得什么好处或影响:

class some_class(parent_class):
    def doOp(self, x, y):
        def add(x, y):
            return x + y
        return add(x, y)

我在一个开源项目中发现了这个,它在嵌套函数内部做了一些有用的事情,但除了调用它之外,绝对没有做任何事情。 (实际代码可以在here 找到。)为什么有人会这样编码?在嵌套函数内部而不是在外部普通函数中编写代码有什么好处或副作用吗?

【问题讨论】:

这是您找到的实际代码,还是您构建的简化示例? 这是一个简化的例子。实际代码可以在这里找到:bazaar.launchpad.net/%7Eopenerp/openobject-server/trunk/… 您的链接(指向 HEAD)现在不准确。试试看:bazaar.launchpad.net/~openerp/openobject-server/trunk/annotate/… 你说得对,克雷格。谢谢。 【参考方案1】:

通常你这样做是为了closures

def make_adder(x):
    def add(y):
        return x + y
    return add

plus5 = make_adder(5)
print(plus5(12))  # prints 17

内部函数可以访问封闭范围内的变量(在本例中为局部变量x)。如果您没有从封闭范围访问任何变量,它们实际上只是具有不同范围的普通函数。

【讨论】:

为此我更喜欢部分:plus5 = functools.partial(operator.add, 5)。装饰器将是闭包的更好示例。 谢谢,但正如您在我发布的 sn-p 中看到的那样,这里的情况并非如此:嵌套函数只是在外部函数中被调用。【参考方案2】:

除了函数生成器,内部函数创建几乎是函数生成器的定义,我创建嵌套函数的原因是为了提高可读性。如果我有一个只能由外部函数调用的小函数,那么我将内联定义,这样您就不必跳过来确定该函数在做什么。如果以后发现需要重用该函数,我总是可以将内部方法移到封装方法之外。

玩具示例:

import sys

def Foo():
    def e(s):
        sys.stderr.write('ERROR: ')
        sys.stderr.write(s)
        sys.stderr.write('\n')
    e('I regret to inform you')
    e('that a shameful thing has happened.')
    e('Thus, I must issue this desultory message')
    e('across numerous lines.')
Foo()

【讨论】:

唯一的问题是这有时会使单元测试变得更加困难,因为您无法访问内部函数。 它们看起来很可爱! FWIY @Challenger5 如果内部函数类似于私有类函数,它们无论如何都没有经过单元测试。我已经开始这样做是为了使方法更具可读性,同时保持定义接近所讨论的方法。【参考方案3】:

使用内部方法的一个潜在好处是它允许您使用外部方法局部变量而不将它们作为参数传递。

def helper(feature, resultBuffer):
  resultBuffer.print(feature)
  resultBuffer.printLine()
  resultBuffer.flush()

def save(item, resultBuffer):

  helper(item.description, resultBuffer)
  helper(item.size, resultBuffer)
  helper(item.type, resultBuffer)

可以写成这样,可以说更好读

def save(item, resultBuffer):

  def helper(feature):
    resultBuffer.print(feature)
    resultBuffer.printLine()
    resultBuffer.flush()

  helper(item.description)
  helper(item.size)
  helper(item.type)

【讨论】:

【参考方案4】:

我想不出这样的代码有什么好的理由。

也许旧版本中的内部功能是有原因的,就像其他 Ops 一样。

例如,这让稍微更有意义:

class some_class(parent_class):
    def doOp(self, op, x, y):
        def add(x, y):
            return x + y
        def sub(x,y):
            return x - y
        return locals()[op](x,y)

some_class().doOp('add', 1,2)

但是内部函数应该是(“私有”)类方法:

class some_class(object):
    def _add(self, x, y):
        return x + y
    def doOp(self, x, y):
        return self._add(x,y)

【讨论】:

是的,也许 doOp 需要一个字符串来指定在参数上使用哪个运算符... @ArtOfWarfare 最好只使用模块。类用于状态。【参考方案5】:

局部方法背后的思想类似于局部变量:不要污染更大的名称空间。显然,好处是有限的,因为大多数语言也不直接提供此类功能。

【讨论】:

【参考方案6】:

你确定代码是这样的吗?做这样的事情的正常原因是创建一个部分 - 一个带有烘焙参数的函数。调用外部函数会返回一个不需要参数的可调用对象,因此可以在无法传递参数的地方存储和使用。但是,您发布的代码不会这样做 - 它立即调用函数并返回结果,而不是可调用的。发布您看到的实际代码可能会很有用。

【讨论】:

我在对我的问题的评论中添加了指向原始代码的链接。如您所见,我的示例是一个简化的示例,但仍然几乎相同。

以上是关于Python中的嵌套函数的主要内容,如果未能解决你的问题,请参考以下文章

Python中的嵌套函数

了解 Python 中的嵌套 lambda 函数行为

对python中的参数进行操作的嵌套函数装饰器

是否有等效于 C 中的嵌套递归函数?

如何在python中实现函数式编程中的嵌套for循环?

python3--嵌套函数