详解高阶函数和闭包 | 手把手教你入门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

相关文章
|
21天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
26天前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
本文将引导读者了解如何使用Python进行数据分析,从安装必要的库到执行基础的数据操作和可视化。通过本文的学习,你将能够开始自己的数据分析之旅,并掌握如何利用Python来揭示数据背后的故事。
|
22天前
|
IDE 程序员 开发工具
Python编程入门:打造你的第一个程序
迈出编程的第一步,就像在未知的海洋中航行。本文是你启航的指南针,带你了解Python这门语言的魅力所在,并手把手教你构建第一个属于自己的程序。从安装环境到编写代码,我们将一步步走过这段旅程。准备好了吗?让我们开始吧!
|
22天前
|
测试技术 开发者 Python
探索Python中的装饰器:从入门到实践
装饰器,在Python中是一块强大的语法糖,它允许我们在不修改原函数代码的情况下增加额外的功能。本文将通过简单易懂的语言和实例,带你一步步了解装饰器的基本概念、使用方法以及如何自定义装饰器。我们还将探讨装饰器在实战中的应用,让你能够在实际编程中灵活运用这一技术。
37 7
|
24天前
|
Python
闭包(Closure)是**Python中的一种高级特性
闭包(Closure)是**Python中的一种高级特性
40 8
|
23天前
|
开发者 Python
Python中的装饰器:从入门到实践
本文将深入探讨Python的装饰器,这一强大工具允许开发者在不修改现有函数代码的情况下增加额外的功能。我们将通过实例学习如何创建和应用装饰器,并探索它们背后的原理和高级用法。
37 5
|
22天前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
59 3
|
26天前
|
Python
Python编程入门:从零开始的代码旅程
本文是一篇针对Python编程初学者的入门指南,将介绍Python的基本语法、数据类型、控制结构以及函数等概念。文章旨在帮助读者快速掌握Python编程的基础知识,并能够编写简单的Python程序。通过本文的学习,读者将能够理解Python代码的基本结构和逻辑,为进一步深入学习打下坚实的基础。
|
29天前
|
数据采集 XML 存储
构建高效的Python网络爬虫:从入门到实践
本文旨在通过深入浅出的方式,引导读者从零开始构建一个高效的Python网络爬虫。我们将探索爬虫的基本原理、核心组件以及如何利用Python的强大库进行数据抓取和处理。文章不仅提供理论指导,还结合实战案例,让读者能够快速掌握爬虫技术,并应用于实际项目中。无论你是编程新手还是有一定基础的开发者,都能在这篇文章中找到有价值的内容。
|
29天前
|
设计模式 缓存 开发者
Python中的装饰器:从入门到实践####
本文深入探讨了Python中强大的元编程工具——装饰器,它能够以简洁优雅的方式扩展函数或方法的功能。通过具体实例和逐步解析,文章不仅介绍了装饰器的基本原理、常见用法及高级应用,还揭示了其背后的设计理念与实现机制,旨在帮助读者从理论到实战全面掌握这一技术,提升代码的可读性、可维护性和复用性。 ####