微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

何时在函数内部创建嵌套函数以及何时从外部调用它?

如何解决何时在函数内部创建嵌套函数以及何时从外部调用它?

我见过一些具有这些结构的代码

结构一:在函数内部创建一个内部函数

def external_func(num):
    def internal_func(num2):
        return num2*2
    return internal_func(num + 10)


test = external_func(5)
print(test)

结构 2:一个函数正在调用一个在其自身之外的函数

def _internal_func2(num2):
    return num2 * 2

def external_func2(num):
    return _internal_func2(num + 10)

test2 = external_func2(5)
print(test2)

对于这种特殊情况,两个函数都提供相同的输出。我应该在哪里以及为什么要使用这些结构中的每一种?

解决方法

结构 1 的主要好处之一是它使 internal_func 局部作用域为 external_func。换句话说,您明确表示 internal_funcexternal_func 访问。就像在 external_func 中定义的任何其他常规变量一样对待它。类似于没有分散的全局变量,有时您想将一个实现“隐藏”在其他函数中。

然后您可以在其他方法中使用其他类似名称的 internal_func 并且它们的名称不会冲突:

In [39]: def external_func_x2(num):
    ...:     def f():
    ...:         return num * 2
    ...:     return internal_func
    ...: 

In [40]: def external_func_x3(num):
    ...:     def f():
    ...:         return num * 3
    ...:     return internal_func

一个常见的目的是制作基于特定条件生成其他函数的函数:

In [44]: def make_multiplier(mult):
    ...:     def f(num):
    ...:         return num*mult
    ...:     return f
    ...: 

In [45]: x4 = make_multiplier(4)

In [46]: x4(8)
Out[46]: 32

In [47]: x3 = make_multiplier(3)

In [48]: x3(8)
Out[48]: 24

您可以使用结构 2(或使用 functools.partial)执行上述相同的示例,但这样会降低可读性,并且您需要在外部作用域中公开此内部 f 函数/命名空间,即使它仅由 make_multiplier 方法使用。再一次,把它想象成在类中隐藏方法。您还必须将参数从一个函数传递到另一个函数,而不是像结构 1 那样使用闭包。

如果您将此 make_multiplier 作为某个库/API 的一部分,使用结构 1“隐藏”此 f 函数并使其对库的客户/用户更清晰、更易读/API 他们只需要“查看”make_multiplier 方法。

还有一个关于可维护性的争论。如果你需要修改 make_multiplier,很明显你需要修改 f,并且你可以很确定修改 f 不会破坏你代码的其他部分,因为没有人使用它而不是 make_multiplier

结构 2 是“将大功能拆分为更易于管理和可重用的小功能”的标准良好做法。与结构 1 相比,它的主要优点是可测试性和可重用性。直接测试和模拟 _internal_func2 容易得多,无需调用 external_func2,如果 external_func2 本身调用起来特别复杂,这很好。编写直接针对嵌套内部函数的测试也非常困难

它还使 _internal_func2 可以被其他方法重用。将其与上面结构 1 的示例进行比较,如果您发现自己编写了嵌套在许多 f 中的相同内部 external_func,那么最好将其移出并转换为结构 2 样式。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。