首页Python【Python基础】14....

【Python基础】14.函数基础2——匿名函数、闭包


本系列文章配套代码获取有以下三种途径:

  • 可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):

https://returu.github.io/Python_Basic/lab/index.html
链接:https://pan.baidu.com/s/1x2Ynh_VibPY2u-HWTaJo8w?pwd=mnsj 提取码:mnsj
  • 前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Basic

—————————————————

1.将函数作为其他函数的参数或返回值:

在Python中。万物皆对象,函数也不例外。因此,可以将函数赋值给一个变量,也可以将其作为其他函数的参数或者返回值。

 1# 首先定义一个函数,该函数不带参数
2>>def print_something():
3...     print('something')
4
5# 再定义第二个函数,该函数有一个参数func,代表要运行的函数
6>>def run_something(func):
7...     func()
8
9# 将第一个函数作为参数传递给第二个函数
10>>> run_something(print_something)
11something

下面再运行一个带有参数的函数。

 1# 首先定义一个求和函数,其参数为可变数量的参数
2>>def add_args(*args):
3...     print(sum(args))
4
5# 再定义第二个函数,参数func代表要运行的函数,*args代表可变数量的参数
6>>def run_something(func , *args):
7...     func(*args)
8
9# 将参数传递给第二个函数
10>>> run_something(add_args , 2 , 3 , 4)
119

需要注意的是,上面传递的是函数名func,而不是func()。加圆括号()表示调用该函数,不加圆括号表示引用该函数。

 1>>def print_something():
2...     print('something')
3
4# 引用函数
5>>> print_something
6<function __main__.print_something()>
7
8# 调用函数
9>>> print_something()
10something

2.匿名函数:

匿名函数是使用lambda保留字定义的特色函数,也称为lambda函数。

其语法形式如下,匿名函数并非没有名字,而是将函数名作为函数结果返回。

1<函数名> = lambda <参数列表> : <表达式>

其等价于:

1def <函数名> (<参数列表>):
2    return <表达式>

lambda函数适用于定义简单的、能够在一行代码内表示的函数,返回一个函数类型。

1>>> f = lambda x , y : x * y
2>>> type(f)
3function
4>>> f(2 , 3)
56

3.内部函数:

在一个函数的内部可以再定义另一个函数。

1>>def outer_func(x , y):
2...     def inner_func(a , b):
3...         return a + b
4...     return inner_func(x , y)
5
6>>> outer_func(1 , 2)
73

如果需要在另一个函数内执行多次复杂任务,内部函数会非常有用,可以避免循环或重复代码。

4.闭包(Closure)

4.1 闭包定义:

闭包就是在外部函数中定义一个内部函数,内部函数可以修改和记录在该函数之外创建的变量的值,外部函数的返回值是内部函数。

需要注意的是,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。

创建一个闭包需要满足以下几点:

  • 必须有一个内部函数;

  • 内部函数必须引用外部函数中的变量;

  • 外部函数的返回值必须是内部函数。
 1>>def outer_func(x):      # 外部函数
2...     print(f'外部层函数的参数:{x}')
3...     def inner_func(y):  # 内部函数
4...         print(f'内层函数的参数:{y}')
5...         return x + y
6...     return inner_func   # 返回值为内部函数
7
8>>> result = outer_func(1)
9外部层函数的参数:2
10>>> result
11<function __main__.outer_func.<locals>.inner_func(y)>
12>>> result(2)
13内层函数的参数:2
143

4.2 __closure__属性:

闭包的__closure__属性记录着自由变量的参数对象地址,当闭包被调用时,系统就会根据该地址找到自由变量,完成整体的函数调用。

1>>> result.__closure__
2(<cell at 0x000001C6BDD082E0int object at 0x000001C6B88D6950>,)

可以看到__closure__属性显示的内容是一个int类型对象,这个对象就是result中自由变量x的初始值。__closure__属性的类型是一个元祖,表明闭包支持多个自由变量的形式。

4.3 闭包用途:

闭包的用途主要是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。

1>>def outer_func(a):
2...     b = 10
3...     def inner_func(x):
4...         print(f'{a}*{x}+{b}')
5...  
6...     return inner_func
7
8>>> F = outer_func(5)
9>>> F(20)

内部函数inner_func()可以访问嵌套作用域内的链各个变量:参数a和变量b。这种嵌套作用域引用,就是Python函数能够保留状态信息的主要方法了。

4.4 nonlocal关键字:

本地函数可以通过global关键字声明对全局变量进行引用修改,那么,内嵌函数内部想对嵌套作用域中的变量进行修改,可以通过nonlocal关键字进行声明。

 1>>> def outer_func(a):
2...     b = 10
3...     def inner_func(x):
4...         nonlocal b
5...         b += 1
6...         print(f'{a}*{x}+{b}')
7...  
8...     return inner_func
9
10>>> F = outer_func(5)
11>>> F(20)
125*20+11
13>>> F(20)
145*20+12
15>>> F(20)
165*20+13

4.4 闭包的缺点:

由于闭包会使得函数中的变量都被保存在内存中,会增加内存消耗。

因此不能滥用闭包,否则会造成程序的性能问题,导致内存泄漏。

本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments