详解高阶函数和闭包 | 手把手教你入门Python之四十五

简介: 本节重点介绍高阶函数 ,闭包

上一篇:递归函数和匿名函数的使用介绍 | 手把手教你入门Python之四十四
下一篇:5个案例详解装饰器 | 手把手教你入门Python之四十六

本文来自于千锋教育在阿里云开发者社区学习中心上线课程《Python入门2020最新大课》,主讲人姜伟。

高阶函数

在Python中,函数其实也是⼀种数据类型。

def test():
 return 'hello world'
print(type(test)) # <class 'function'>

函数对应的数据类型是 function ,可以把它当做是⼀种复杂的数据类型。
既然同样都是⼀种数据类型,我们就可以把它当做数字或者字符串来处理。

定义⼀个变量指向函数

在Python中,我们还可以定义⼀个变量,让它来指向⼀个函数,相当于给函数起了⼀个别名。

def test():
 return 'hello wrold'
fun = test # 定义了⼀个变量fun,让它指向了 test 这个函数
print(fun()) # 使⽤fun()可以直接调⽤test这个函数
print(id(fun)) # 1819677672040
print(id(test)) # 1819677672040

注意:在定义⼀个变量表示⼀个函数时,函数后⾯不能加括号!加括号表示的是调⽤这个函数。

def test():
 return 'hello world'
result = test() # 这种写法是调⽤test函数,并把函数的返回值赋值给result变量
print(result()) # 这⾥会报错 TypeError: 'str' object is not callable
fun = test # 这种写法是给test函数起了⼀个别名,注意,这⾥的test后⾯不能加()
fun() # 可以使⽤别名调⽤这个函数

⾼阶函数

既然变量可以指向函数,函数的参数能接收变量,那么⼀个函数就可以接收另⼀个函数作为参数,同样,我们还可以把⼀个函数当做另⼀个函数的返回值。这种函数的使⽤⽅式我们称之为⾼阶函数。

函数做为另⼀个函数的参数

def test(age,action):
 if age < 18:
 print('您还没满⼗⼋岁,请退出')
 action() # 把参数action直接当做⼀个函数来调⽤
def smoke():
 print('我已经年满⼗⼋岁了,我想抽烟')

my_action = smoke # 定义⼀个变量my_action,让它指向smoke函数
test(21, my_action) # 将my_action传给 test 函数作为它的参数
test(21,smoke) # 还可以不再定义⼀个新的变量,直接传⼊函数名

函数作为另⼀个函数的返回值

def test():
 print('我是test函数⾥输⼊的内容')
def demo():
 print('我是demo⾥输⼊的内容')
 return test # test 函数作为demo函数的返回值
result = demo() # 我是demo⾥输⼊的内容 调⽤ demo 函数,把demo函数的返回值赋值给 result
print(type(result)) # <class 'function'> result 的类型是⼀个函数
result() # 我是demo⾥输⼊的内容 我是test函数⾥输⼊的内容 既然result是⼀个函数,那么就可
以直接使⽤() 调⽤这个函数
demo()() # 我是demo⾥输⼊的内容 我是test函数⾥输⼊的内容

image.png
image.png
image.png

image.png

闭包

函数只是⼀段可执⾏代码,编译后就“固化”了,每个函数在内存中只有⼀份实例,得到函数的⼊⼝点便可以执⾏函数了。函数还可以嵌套定义,即在⼀个函数内部可以定义另⼀个函数,有了嵌套函数这种结构,便会产⽣闭包问题。

函数嵌套

在函数⾥⾯还可以定义函数,可以嵌套多层,执⾏需要被调⽤。

def outer():
 print('outer----hello')
 def inner(): # inner这个函数是在outer函数内部定义的
 print('inner----hello')
 inner() # inner函数只在outer函数内部可⻅
outer()
# inner() 这⾥会报错,在outer函数外部⽆法访问到inner函数

什么是闭包

闭包是由函数及其相关的引⽤环境组合⽽成的实体(即:闭包=函数块+引⽤环境)。

def outer(n):
 num = n
 def inner():
 return num+1
 return inner
print(outer(3)()) # 4
print(outer(5)()) # 5

在这段程序中,函数 inner 是函数 outer 的内嵌函数,并且 inner 函数是outer函数的返回值。我们注意到⼀个问题:内嵌函数 inner 中引⽤到外层函数中的局部变量num,Python解释器会这么处理这个问题呢? 先让我们来看看这段代码的运⾏结果,当我们调⽤分别由不同的参数调⽤ outer 函数得到的函数时,得到的结果是隔离的(相互不影响),也就是说每次调⽤outer函数后都将⽣成并保存⼀个新的局部变量num,这⾥outer函数返回的就是闭包。 如果在⼀个内部函数⾥,对在外部作⽤域(但不是在全局作⽤域)的变量进⾏引⽤,那么内部函数就被认为是闭包(closure)。

修改外部变量的值

闭包⾥默认不能修改外部变量。

def outer(n):
 num = n
 def inner():
 num = num + 1
 return num
 return inner
print(outer(1)())

上述代码运⾏时会报错!

UnboundLocalError: local variable 'num' referenced before assignment

原因分析

在python⾥,只要看到了赋值语句,就会认为赋值语句的左边是⼀个局部变量。 num = num + 1 这段代码⾥, num 在 = 的左边,python解析器会认为我们要修改 inner 函数⾥ num 这个局部变量,⽽这个变量使⽤之前是未声明的,所以会报错。

解决方案

我们分析过,报错的原因在于当我们在闭包内修改外部变量时,会被python解析器误会为内部函数的局部变量。所以,解决⽅案就在于,我们需要想办法,让解析器知道我们不是要修改局部变量,⽽是要修改外部变量。

  • 解决⽅法:使⽤ nonlocal 关键字
def outer(n):
 num = n
 def inner():
 nonlocal num # 修改前使⽤nonlocal关键字对 num 变量进⾏说明
 num = num + 1
 return num
 return inner
print(outer(2)())

image.png

计算代码的执行时长

image.png
image.png

相关文章
|
1天前
|
缓存 算法 数据处理
Python入门:9.递归函数和高阶函数
在 Python 编程中,函数是核心组成部分之一。递归函数和高阶函数是 Python 中两个非常重要的特性。递归函数帮助我们以更直观的方式处理重复性问题,而高阶函数通过函数作为参数或返回值,为代码增添了极大的灵活性和优雅性。无论是实现复杂的算法还是处理数据流,这些工具都在开发者的工具箱中扮演着重要角色。本文将从概念入手,逐步带你掌握递归函数、匿名函数(lambda)以及高阶函数的核心要领和应用技巧。
Python入门:9.递归函数和高阶函数
|
1天前
|
开发者 Python
Python入门:8.Python中的函数
### 引言 在编写程序时,函数是一种强大的工具。它们可以将代码逻辑模块化,减少重复代码的编写,并提高程序的可读性和可维护性。无论是初学者还是资深开发者,深入理解函数的使用和设计都是编写高质量代码的基础。本文将从基础概念开始,逐步讲解 Python 中的函数及其高级特性。
Python入门:8.Python中的函数
|
1天前
|
存储 SQL 索引
Python入门:7.Pythond的内置容器
Python 提供了强大的内置容器(container)类型,用于存储和操作数据。容器是 Python 数据结构的核心部分,理解它们对于写出高效、可读的代码至关重要。在这篇博客中,我们将详细介绍 Python 的五种主要内置容器:字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)。
Python入门:7.Pythond的内置容器
|
1天前
|
存储 索引 Python
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
|
1天前
|
知识图谱 Python
Python入门:4.Python中的运算符
Python是一间强大而且便捷的编程语言,支持多种类型的运算符。在Python中,运算符被分为算术运算符、赋值运算符、复合赋值运算符、比较运算符和逻辑运算符等。本文将从基础到进阶进行分析,并通过一个综合案例展示其实际应用。
|
1天前
|
程序员 UED Python
Python入门:3.Python的输入和输出格式化
在 Python 编程中,输入与输出是程序与用户交互的核心部分。而输出格式化更是对程序表达能力的极大增强,可以让结果以清晰、美观且易读的方式呈现给用户。本文将深入探讨 Python 的输入与输出操作,特别是如何使用格式化方法来提升代码质量和可读性。
Python入门:3.Python的输入和输出格式化
|
1天前
|
存储 Linux iOS开发
Python入门:2.注释与变量的全面解析
在学习Python编程的过程中,注释和变量是必须掌握的两个基础概念。注释帮助我们理解代码的意图,而变量则是用于存储和操作数据的核心工具。熟练掌握这两者,不仅能提高代码的可读性和维护性,还能为后续学习复杂编程概念打下坚实的基础。
Python入门:2.注释与变量的全面解析
|
1天前
|
机器学习/深度学习 人工智能 算法框架/工具
Python入门:1.Python介绍
Python是一种功能强大、易于学习和运行的解释型高级语言。由**Guido van Rossum**于1991年创建,Python以其简洁、易读和十分工程化的设计而带来了庞大的用户群体和丰富的应用场景。这个语言在全球范围内都被认为是**创新和效率的重要工具**。
Python入门:1.Python介绍
|
1月前
|
存储 数据挖掘 数据处理
Python Pandas入门:行与列快速上手与优化技巧
Pandas是Python中强大的数据分析库,广泛应用于数据科学和数据分析领域。本文为初学者介绍Pandas的基本操作,包括安装、创建DataFrame、行与列的操作及优化技巧。通过实例讲解如何选择、添加、删除行与列,并提供链式操作、向量化处理、索引优化等高效使用Pandas的建议,帮助用户在实际工作中更便捷地处理数据。
47 2
|
4月前
|
Python
【python从入门到精通】-- 第一战:安装python
【python从入门到精通】-- 第一战:安装python
79 0

热门文章

最新文章

推荐镜像

更多