Py函数直接传入root是啥意思_Python内部函数——用处何在?

c1ac27693724186e1704cce8e4d8d1b4.png
这是一篇译文,原文地址:https://realpython.com/inner-functions-what-are-they-good-for/

1. 封装

内部函数可以免受函数之外的情况的影响,也就是说,对于全局命名空间而言,它们是隐藏的。

下面是一个简单的例子:

def outer(num1):def inner_increment(num1):  # 对外部空间隐藏return num1 + 1num2 = inner_increment(num1)print(num1, num2)inner_increment(10)
# outer(10)

如果我们直接调用 inner_increment() 函数,会有报错信息:

Traceback (most recent call last):File "inner.py", line 7, in <module>inner_increment()
NameError: name 'inner_increment' is not defined

注释掉对 inner_increment() 的直接调用,对外部的函数传入参数 10,即 outer(10) 是可以运行的:

10 11
注意:这只是一个例子,虽然这些代码可以运作,但就这个函数而言,可能更好的方式是把 inner_increment() 定义为存在于外部空间的“私有”函数,即在函数名前加一个下划线前缀,即 _inner_increment()

下面这个嵌套函数可能是一个更好的使用内部函数的例子:

def factorial(number):# 处理错误if not isinstance(number, int):raise TypeError("Sorry. 'number' must be an integer.")if not number >= 0:raise ValueError("Sorry. 'number' must be zero or positive.")def inner_factorial(number):if number <= 1:return 1return number*inner_factorial(number-1)return inner_factorial(number) # 调用外部函数
print(factorial(4))

在这里,我们把参数验证放在外部函数,而在内部函数中处理关键步骤。


2. 避免自我重复(DRY原则)

有时,我们可能会在一个大型函数中,重复地使用一些代码。比方说,我们写一个处理文件的函数,同时支持文件名或文件对象作为参数:

def process(file_name):def do_stuff(file_process):for line in file_process:print(line)if isinstance(file_name, str):with open(file_name, 'r') as f:do_stuff(f)else:do_stuff(file_name)
注意:再次提醒,可能更常见的情况是,我们直接把 do_stuff() 放在外部,作为一个私有函数,但显然,必要时我们也可以把它作为内部函数隐藏起来。

我们可以写一个更具体的例子。

假如说,我们想了解纽约市的 WIFI 热点数据,可以直接在网上下载对应的 CSV 文件,然后进行统计:

def process(file_name):def do_stuff(file_process):wifi_locations = {}for line in file_process:values = line.split(',')            # 创建一个字典,记录统计数据 wifi_locations[values[1]] = wifi_locations.get(values[1], 0) + 1max_key = 0for name, key in wifi_locations.items():all_locations = sum(wifi_locations.values())if key > max_key:max_key = keybusiness = nameprint(f'纽约市总共有 {all_locations} 个 WIFI 热点,'f'{business} 提供的热点最多,有 {max_key} 个。')if isinstance(file_name, str):with open(file_name, 'r') as f:do_stuff(f)else:do_stuff(file_name)

运行后得到结果如下:

>>> process('NAME_OF_THE.csv')
纽约市总共有 1251 个 WiFi 热点,Starbucks 提供的热点最多,有 212 个。

3. 闭包与工厂函数

接下来我们要讨论的是使用内部函数最重要的理由。在之前的例子中,内部函数都是一个常规函数,只是恰好被嵌套在另一个函数中而已。也就是说,我们完全用其它方式定义它们(如之前已经提示的),并非一定要使用内部函数。

而在考虑闭包的时候,我们就必须使用嵌套函数了。

什么是闭包

闭包可以使内部函数记住它所在空间的具体状态。新手们常常以为内部函数就是闭包,准确地说,应该是内部函数制造了闭包。所谓闭包,所“封闭”的是函数帧中的局部变量。

一个例子

以下是一个例子:

def generate_power(number):"""    Examples of use:>>> raise_two = generate_power(2)>>> raise_three = generate_power(3)>>> print(raise_two(7))128>>> print(raise_three(5))243"""# 定义内部函数def nth_power(power):return number ** power# 将函数作为外部函数的结果返回return nth_power

对例子的解释

让我们看看这个例子中具体发生了什么:

  1. generate_power() 是一个工厂函数,每次调用它时,会返回一个新创建的函数,因此,raise_tworaise_three 指向的是这些新创建的函数;
  2. 这些新创建的函数,需要一个参数 power,返回的值是 number**power
  3. 那么,这个 number 的值是怎么来的呢?这就是闭包发生作用的地方:nth_power() 函数是从外部函数,即工厂函数获取 number 的值的。整个过程可以分解步骤如下:
  • 调用外部函数:generate_power(2);
  • 创建函数 nth_power(),它需要一个参数 power
  • 保存 nth_power() 函数帧的状态,其中包括 number=2
  • 将保存的函数帧状态传递给 generate_power() 函数;
  • 返回 nth_power() 函数;

换句话说,闭包为 nth_power() 函数提供了初始化数据并将它返回。因此,我们调用这个被返回的函数时,总是可以在其函数帧中找到 number=2

一个实际应用

现在,让我们考虑一个真实世界中的例子:

def has_permission(page):def inner(username):if username == 'Admin':return "'{0}' does have access to {1}.".format(username, page)else:return "'{0}' does NOT have access to {1}.".format(username, page)return innercurrent_user = has_permission('Admin Area')
print(current_user('Admin'))random_user = has_permission('Admin Area')
print(random_user('Not Admin'))

这是一个简化版的权限判断函数,我们也可以做简单修改,从 session 中获取用户信息,进而判断这个用户是否具有接入某个路由的权限。显然,我们会从数据库中查询用户权限,而不是检查用户名是否等于 'Admin'


总结

闭包与函数工厂是内部函数最常见、最主要的用处。大多数情况下,如果你看到一个带装饰器的函数,这个装饰器就是一个函数工厂,它以一个函数作为参数,并返回一个新的函数,新的函数使用闭包包括了作为参数的函数。

换句话说,装饰器就是一个语法糖,它的基本流程其实和上面所举的 generate_power() 的例子是一致的。

以下是最后一个例子:

def generate_power(exponent):def decorator(f):def inner(*args):result = f(*args)return exponent**resultreturn innerreturn decorator@generate_power(2)
def raise_two(n):return n print(raise_two(7))@generate_power(3)
def raise_three(n):return n print(raise_two(5))

如果你的代码编辑器允许的话,可以尝试把 generate_power(exponent)generate_power(number) 并排对比,以理解我们所讨论的概念。(比如说,可以用 Sublime Text 中的分栏功能)

如果你还没写出这两个函数的话,建议还是亲自在编辑器中敲出来一次,对编程新手来说,写代码就行骑自行车:你必须亲自上手。

敲出这些代码后,你就能看出,它们产生了类似的结果,但也有一些不同。对于还没有用过装饰器的人来说,注意到这些不同,就是理解它们的开始。


END

公众号:ReadingPython

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 和 Windows 平台不同的 UCS-2 编码

2019独角兽企业重金招聘Python工程师标准>>> 以下是有关两个平台 UCS-2 编码的潜规则&#xff1a; 1, UCS-2 不等于 UTF-16。 UTF-16 每个字节使用 ASCII 字符范围编码&#xff0c;而 UCS-2 对每个字节的编码可以超出 ASCII 字符范围。UCS-2 和 UTF-16 对每个字符至…

vld检测不输出_输出轴热处理形变超差,找找原因

这里有最实用的技术&#xff0c;点击↑↑关注作者&#xff1a;阚亚威单位&#xff1a;镇江液压股份有限公司来源&#xff1a;《金属加工(热加工)》杂志我公司摆线液压马达输出轴材料主要为20CrMnTi&#xff0c;热处理工艺为渗碳直接淬火低温回火&#xff0c;工艺如图1所示。近期…

java 独占锁_锁分类(独占锁、分拆锁、分离锁、分布式锁)

一、java内存模型提到同步、锁&#xff0c;就必须提到Java的内存模型&#xff0c;为了提高程序的执行效率&#xff0c;java也吸收了传统应用程序的多级缓存体系。在共享内存的多处理器体系架构中&#xff0c;每个处理器都拥有自己的缓存&#xff0c;并且定期地与主内存进行协调…

url模糊匹配优化_企业必备的网站SEO优化解决方案

一、网站优化与调整倡议一个好网站不只要满足阅读者&#xff0c;还要契合搜索引擎规则、满足搜索引擎快照抓取、赋予评级、提升关键词排序等。我们站在用户角度和搜索引擎规则根底上为您提供一套完好的SEO处理计划SEO处理计划SEO倡议大纲&#xff1a;1、目的客户剖析与定位&…

中文能用rsa加密吗_外文文献数据库能用中文词进行检索吗?

大家使用外文文献数据库进行检索的时候可能想过一个问题&#xff1a;我们可以使用中文关键词进行检索吗&#xff1f;上文献检索课的老师可能会这样回答&#xff1a;在一般情况下&#xff0c;是不可以的。那么实际情况是怎样的呢&#xff1f;我们找几个外文文献数据库来验证一下…

【maven3学习之三】maven构建一个简单的Hello World

2019独角兽企业重金招聘Python工程师标准>>> 在写之前我先需要配置一下setting.xml。 首先是localRepository&#xff0c;默认情况下是【你的用户目录】/.m2/repository作为本地库的目录&#xff0c;但是我希望将其放在D:\maven_localRepository的目录下面。 如果…

python营销骗局_python案例:金融营销活动中欺诈用户行为分析

首先&#xff0c;数据导入 1 importnumpy as np2 importpandas as pd3 from collections importCounter4 importmatplotlib.pyplot as plt5 from pymining importitemmining,assocrules,perftesting,seqmining6 importpyecharts as pe7 rtpd.read_csv(r"E:\transaction_tr…

你真的会数钱吗?

本文已迁移至&#xff1a;http://thinkinside.tk/2013/01/01/money.html 快年底了&#xff0c;假如你们公司的美国总部给每个人发了一笔201212.21美元的特别奖金&#xff0c;作为程序员的你&#xff0c; 该如何把这笔钱收入囊中&#xff1f; Table of Contents 1 美元&#xff…

Maven 系统环境变量配置

Download http://maven.apache.org/download.cgi http://mirrors.shu.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.zip 环境变量 1.添加 MAVEN_HOME&#xff1a; 变量名&#xff1a;MAVEN_HOME  变量值&#xff1a;C:\Program\apache-maven-3.5.4 注…

eclipse中文乱码解决_解决git status显示中文文件名乱码问题

使用 git status 查看本地有改动但未提交的中文文件名时&#xff0c;发现会显示为一串数字&#xff0c;没有显示中文的文件名。具体如下所示&#xff1a;$ git status# 位于分支 master# 尚未暂存以备提交的变更:# (使用 "git add ..." 更新要提交的内容)# (使用 &qu…

MongoDB 3.X 用户权限控制

摘要&#xff1a; MongoDB 3.0 安全权限访问控制&#xff0c;在添加用户上面3.0版本和之前的版本有很大的区别&#xff0c;这里就说明下3.0的添加用户的方法。 环境、测试&#xff1a; 在安装MongoDB之后&#xff0c;先关闭auth认证&#xff0c;进入查看数据库&#xff0c;只有…

java enum 变量_java枚举使用详解

package com.ljq.test;/*** 枚举用法详解** author jiqinlin**/public class TestEnum {/*** 普通枚举** author jiqinlin**/public enum ColorEnum {red, green, yellow, blue;}/*** 枚举像普通的类一样可以添加属性和方法&#xff0c;可以为它添加静态和非静态的属性或方法**…

c#小游戏_C#小游戏—钢铁侠VS太空侵略者

身为漫威迷&#xff0c;最近又把《钢铁侠》和《复仇者联盟》系列又重温了一遍&#xff0c;真的是印证了那句话&#xff1a;“读书百遍&#xff0c;其意自现”。看电影一个道理&#xff0c;每看一遍&#xff0c;都有不懂的感受~ 不知道大伙是不是也有同样的感受&#xff0c;对于…

VMware Workstation 虚拟机性能优化指南

我们经常使用虚拟机来体验各种新系统&#xff0c;做各类新鲜应用的测试&#xff0c;由于VMware Workstation虚拟机功能强大&#xff0c;又适用于最新的 Windows / linux /Sun等平台&#xff0c;而且操作方便&#xff0c;所以其普及率很高&#xff01;而 VMware Workstation 本身…

pytorch已经安装成功了为什么不能使用import_使用auto keras的过程

成功安装的总结&#xff1a;1、创建环境名为mykeras、python版本为3.6的独立环境conda create --name mykeras python3.62、用pip安装 torch0.4.1&#xff08;一定要指定版本&#xff0c;否者安装auto keras时报错&#xff09;# Python 3.6 pip install https://download.pytor…

mysql可能锁的表命令_mysql 默许是表级锁一些不太常用命令

mysql 默认是表级锁一些不太常用命令1&#xff0c;mysql默认的是表级锁。如果是启用InnoDB存储引擎那么该数据库支持行级锁。2&#xff0c;查看数据库是否支持innodb的命令SHOW variables like "have_%";另一条命令SHOW ENGINES;更为准确。查看mysql数据库的详细信息…

python制作二级菜单_Python_简单三级菜单制作

一:制作要求 1.三级菜单  2.可依次选择进入各子菜单  3.所需新知识点:字典,列表 *本文通过三种方法完成,第一种:只使用循环,第二种:使用列表,第三种:使用字典 二:FlowChart流程图与上图对应,实现方式图解:while用来判断输入的数据和允许输入数据中的哪一项匹配,if来进行判断…

html5 js

2019独角兽企业重金招聘Python工程师标准>>> http://labs.hyperandroid.com/mathmayhem 转载于:https://my.oschina.net/u/201125/blog/100934

python画图如何调整图例位置_Python-如何将图例排除在情节之外

小编典典 有很多方法可以做你想要的。要添加inalis和Navi所说的内容&#xff0c;可以使用bbox_to_anchor关键字参数将图例部分地放置在轴外and/or 减小字体大小。 在考虑减小字体大小&#xff08;这会使阅读起来非常困难&#xff09;之前&#xff0c;请尝试将图例放在不同的位置…

Haproxy 与 Cookie

1 什么是cookie ? 参考 cookie http://baike.baidu.com/view/835.htm Cookie&#xff0c;有时也用其复数形式Cookies&#xff0c;指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据&#xff08;通常经过加密&#xff09;。定义于RFC2109&#xff0…