Python学习笔记——函数

本文最后更新于:2022年5月23日 凌晨

本文章用到的语言:Python

函数作为对象

在Python中,函数也是对象,所以我们可以把函数分配给变量、存储在数据结构中、作为参数传递给其他函数,也能作为其他函数的返回值。
初次看到这些内容的时候,我是挺惊讶而且发自内心的“すごい!”并且迫不及待地想要理解和掌握。
感觉写文章就是一个非常不错的方式,所以在这里我会尝试用自己所理解到的东西来完成这篇文章。
如果有什么问题的话可以尝试联系我~ 联系我

怎么理解函数是对象

现在有这样一个东西:

1
2
def add(a, b):
return a + b

这就是一个加法函数,传入 a 和 b 的值然后返回二者相加的值,我们可以在控制台调用它得到这样一个结果:

1
2
>>> add(1, 2)
3

如果我现在这么做的话(可以思考一下这段代码做了什么以及输出的结果):

1
2
>>> another_add = add
>>> another_add(2, 3)

没错,输出的结果就是5
接下来我们把原来定义的add函数用del删除,再调用another_add试试看:

1
2
3
4
5
6
>>> del add
>>> add(1, 2)
NameError: name 'add' is not defined

>>> another_add(2, 3)
5

现在add用不了了,但是another_add还能用,为什么呢?因为函数对象及其名称是相互独立的实体:指向函数的变量和函数本身实际上是彼此独立的
这边可以了解一下下面这些东西(引用[1]):

变量是标签

变量常被描述为可用于存储值的盒子。
一种好得多的定义是,变量是可以赋给值的标签,也可以说变量指向特定的值。

以下是扩展

Python在创建函数时都会为每个函数附加一个用于调试的字符串标识符,使用__name__属性来访问它:

1
2
3
4
>>> add.__name__
'add'
>>> another.__name__
'add'

PS:当然是在add没被删除之前调用的,删除后调用了会报错:NameError: name 'add' is not defined
由于是在创建函数的时候给出的标识符,所以即使把这个函数分配给了另一个变量,这个标识符也不会变

把函数存储在数据结构中!

由于函数是个对象,所以可以把函数也存储在数据结构当中,并且访问或使用他们。
比如把他们塞进列表里:

1
2
3
4
5
6
7
8
9
>>> funcs = [another_add, max, pow]
>>> funcs
[<function add at 0x0000024777A49E50>, <built-in function max>, <built-in function pow>]

>>> for fun in funcs:
... print(fun, fun(2, 3))
<function add at 0x0000024777A49E50> 5
<built-in function max> 3
<built-in function pow> 8

你也可以把它们塞进字典里,同样的,我们尝试访问这个字典,然后试着遍历这个字典并调用这些函数:

1
2
3
4
5
6
7
8
9
10
>>> dic_funcs = {'another_add':another_add, 'max':max, 'pow':pow}
>>> dic_funcs
{'another_add': <function add at 0x0000024777A49E50>, 'max': <built-in function max>, 'pow': <built-in function pow>}

>>> for fun in dic_funcs.values():
... print(fun, fun(2, 3))

<function add at 0x0000024777A49E50> 5
<built-in function max> 3
<built-in function pow> 8

并且,在这些数据结构里的函数对象都可以直接调用,不需要特意为他们分配一个变量:

1
2
3
4
5
>>> funcs[0](2, 3)
5

>>> dic_funcs['max'](3, 4, 5)
5

本小节的补充

<built-in function max>指出max函数是python的一个内置函数,所以给出的不是地址
max函数用于查找可迭代的最大值,关于可迭代,在之后的文章可能会介绍(也是python特性哦)
pow(x, y)函数就是平方函数了,将x的值返回为y的幂

将函数传递给其他函数

由于函数是对象,因此可以将其作为参数传递给其他函数。
让我们通过一个例子来理解下:

1
2
3
def get_max_or_min(fun):
value = fun(10, 4, 2, 8, 6)
print(value)

get_max_or_min函数获取一个函数参数,并调用这个函数得到一个值,然后将它打印出来,在这里可以由函数的名称看出来,我们可以向其中传入maxmin函数
让我们尝试一下:

1
2
3
4
5
>>> get_max_or_min(max)
10

>>> get_max_or_min(min)
2

可以看到都输出了正确的结果
“将函数对象作为参数传递给其他函数的功能非常强大,可以用来将程序中的行为抽象出来并传递出去。”[2]
扩展[2]

“能接受其他函数作为参数的函数称为高阶函数。”
“比如map函数,map接受一个函数对象和一个可迭代对象,然后在可迭代对象中的每个元素上调用该函数来生成结果。”
这里我们调用我们的add函数来看看map函数做了什么:

1
2
>>> list(map(add, [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]))
[2, 4, 6, 8, 10]

可以看出,map函数遍历了整个列表并将add函数应用于每个元素,而且得到了一个新列表对象,存储两数相加后的结果。

嵌套函数

在Python中,甚至可以在函数中定义函数,就是之前写多道系统作业调度模拟程序提到过的东西(戳我跳转文章
在这里我们定义一个用来计算的函数,根据传入字符串的不同返回不同的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> def cal(text, x, y):
def add(a, b):
return a + b
def sub(a, b):
return a - b
if text == 'add':
return add(x, y)
elif text == 'sub':
return sub(x, y)
>>> cal('add', 3, 5)
8
>>> cal('sub', 5, 3)
2

但是需要注意的是嵌套函数的作用域:仅在创建它的函数的内部
如果我们想在函数外部使用这个函数的话,可以像我上边提到的那篇文章中那样,创建一个变量,并把嵌套函数返回给父函数的调用者。
在这里,我就写个根据会员等级判断打折力度的函数来作为例子吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> def discount(level):
def platinum(price):
return price*0.75
def gold(price):
return price*0.8
def sliver(price):
return price*0.85
def copper(price):
return price*0.9
if level == 4:
return platinum
elif level == 3:
return gold
elif level == 2:
return sliver
elif level == 1:
return copper

然后再测试一下:

1
2
3
4
5
6
7
>>> discount(3)
<function discount.<locals>.gold at 0x000001CF0C9BE3A0>
>>> a_customer = discount(3)
>>> a_customer(100)
80.0
>>> discount(3)(100)
80.0

“这意味着函数不仅可以通过参数接受行为,还可以返回行为。”[2]

日后计划

以后学到的有关函数这部分的内容也会一起在这里更新。


  1. 《Python编程 从入门到实践(第2版)》 [美]埃里克·马瑟斯 人民邮电出版社
  2. 《Python Tricks 深入理解python特性》 [德]达恩·巴德尔 人民邮电出版社

这里有一只爱丽丝

希望本文章能够帮到您~


Python学习笔记——函数
https://map1e-g.github.io/2022/04/14/python-learning-1/
作者
MaP1e-G
发布于
2022年4月14日
许可协议