python - 何时在函数内部创建嵌套函数,何时从外部调用它?
问题描述
我见过一些具有这些结构的代码。
结构 1:在函数内部创建内部函数
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_func
只能由. 将其视为在内部定义的任何其他常规变量。与没有分散的全局变量类似,有时您希望将实现“隐藏”在其他函数中。external_func
external_func
然后,您可以internal_func
在其他方法中使用其他类似命名的 's,并且它们的名称不会冲突:
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
's 中,那么最好将其移出并转换为结构 2 样式。
推荐阅读
- javascript - I want to assign id into var but nothing display
- vba - 如何在线迁移 SharePoint 中的 Access 数据库和表单?
- python - 如何将 wav 文件填充到特定长度?
- python - 如何将字符串转换为数据框名称 pandas/python
- android - 无法从 SDCARD Android 应用程序读取文件
- c# - 在非异步 asp.net 页面中调用异步方法
- sql - 使用 SQL Developer 格式将日期时间导入 Oracle DB -“6/26/2018 12:41:00 PM”
- php - 如何发布数据,并使用 Laravel 将其插入数据库?
- javascript - Why is this function youWin not working properly?
- python - 在 Azure jupyter notebook 中安装 TA-LIB,面临 GCC 和未创建轮子的问题