扫描二维码,下载手机APP
下载安卓APP箭头
客服QQ
箭头给我发消息

客服QQ:3315713922
论坛 >编程语言 >内层函数——它们的优点是什么?

内层函数——它们的优点是什么?

课课家iOS游客发布于 2018-03-07 09:55查看:11308回复:1

让我们看一下写内层函数的三个常见原因。

记住:在Python中,函数是“一等公民”,这意味着它们和其他对象平起平坐(例如:整型,字符串,列表,模块等)。你可以动态地创建和销毁它们,把它们传递给其他函数,把它们作为值返回,等等。

1.封装

你使用内层函数来保护它们不受函数外部变化的影响,也就是说把它们从全局作用域藏起来。

这里有一个简单的例子来强调这一概念:

image.png

尝试调用inner_increment()函数

image.png

现在,把inner_increment的调用注释掉,再把对外部函数调用的注释取消,outer(10),把10作为参数传入:

image.png

请记住这仅仅是一个例子,尽管代码得到了期望的结果,但是使用一个前置的下划线把inner_increment()函数变为“私有”函数:_inner_increment()更好。

下面这个递归的例子与使用嵌套函数相比稍微好一些:

image.png

同样测试一下这段代码。使用这种设计模式的一个主要优势在于:在外部函数中对全部参数执行了检查,你可以在内部函数中跳过全部的检查过程。


2.贯彻DRY(Don’t Repeat Yourself )原则

也许你有一个巨型函数,在很多很多地方执行一大段的代码。比如,你可能写了一个函数用来处理文件,并且你希望它既可以接受一个打开文件对象或是一个文件名:

image.png

同样,通常会把do_stuff()作为一个顶层私有函数,但是如果你想要把它作为一个内层函数隐藏起来,你也可以这样做。

image.png

执行函数:

image.png

3.闭包和工厂函数

现在我们要谈到使用内层函数最重要的原因了。目前为止我们看到的全部内层函数的例子都是普通函数,只不过它们凑巧嵌套在另外的函数之中了。换句话说,我们本可以用另外的方式定义这些函数(正如我们谈到的那样),并没有什么特别的理由去嵌套它们。

但是当我们谈到闭包的时候,情况就不一样了:你必须要利用嵌套函数。

什么是闭包?

闭包无非是使内层函数在调用时记住它当前环境的状态。初学者经常认为闭包就是内层函数,而且实际上它是由内层函数导致的。闭包在栈上“封闭”了局部变量,使其在栈创建执行结束后仍然存在。

一个例子

image.png

此处发生了什么?

  1. generate_power()函数是一个工厂方法——简单说就是意味着它每次调用的时候会创建一个新函数,并返回这个新创建的函数,因此raise_two 和raise_three 都是新创建的函数。

  2. 这个新的内层函数做了什么呢?它接受一个单独的参数,power,并且返回number**power

  3. 内层函数从哪得到number的值呢?这就该闭包登场了:nth_power()从外层函数得到power 的值,让我们逐步查看这一过程:

    • 调用外层函数:generate_power(2)

    • 生成一个nth_power()函数,它接受一个单一的参数power

    • 保存nth_power()的状态快照,其中number=2

    • 把这个快照传入generate_power()函数

    • 返回nth_power()函数

换句话说,闭包函数“初始化”了nth_power()函数并将其返回。现在无论你何时调用这个新返回的函数,它都会去查看其私有的快照,也就是包含power=2的那一个。

现实世界

来一个实际例子如何?

image.png

这是一个简化过的函数,用来检查某个特定用户是否有权限访问特定的页面。你可以很容易的修改它从会话中抓取用户信息,查看他们是否具有访问当前路径的正确凭证。我们可以查询数据库来查看许可情况,然后根据是否具有正确的凭证来返回返回正确的视图,而不是检查user是否等于‘Admin’。



收藏(0)0
查看评分情况

全部评分

此主贴暂时没有点赞评分

总计:0

回复分享

版主推荐

    共有1条评论

    • 课课家运营团队
    • Mr ken
    • YUI
    • cappuccino
    • mr jack
    • IT宅男
    • Mright
    • 课课家软考1
    • 选择版块:

    • 标题:

    • 内容

    • 验证码:

    • 标题:

    • 内容

    • 选择版块:

    移动帖子x

    移动到: