「Python 基础」函数与高阶函数
创始人
2024-05-29 09:08:46
0

文章目录

    • 1. 函数
      • 调用函数
      • 定义函数
      • 函数的参数
      • 递归函数
    • 2. 高阶函数
      • map/reduce
      • filter
      • sorted
    • 3. 函数式编程
      • 返回函数
      • 匿名函数
      • 装饰器
      • 偏函数

1. 函数

函数是一种重复代码的抽象方式,Python 内建支持的一种封装;

调用函数

调用一个函数,需要知道函数的名称和参数;函数名是只想一个函数对象的引用

>>> a = abs
>>> a(-1)
1

可以在交互式命令行通过 help(abs) 查看 abs 函数的帮助信息;

数据类型转换

>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False

开平方

# 方法一
>>> import math
>>> math.sqrt(100)
10.0# 方法二
>>> pow(100, 0.5)
10.0# 方法三
>>> 100 ** 0.5
10.0

定义函数

定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。

如果没有 return 语句,函数执行完毕后也会返回结果,只是结果为 None。return None 可以简写为 return。

空函数

定义一个什么事也不做的空函数,可以用 pass 来作为占位符

参数检查

调用函数时,如果参数个数不对,Python 解释器会自动检查出来,并抛出 TypeError

返回多个值

Python 的函数返回多值其实就是返回一个 tuple;在语法上,返回一个 tuple 可以省略括号,而多个变量可以同时接收一个 tuple,按位置赋给对应的值

函数的参数

参数类型说明
位置参数def power(x, n): 传入的值依次赋给对应位置的参数
默认参数def power(x, n=2): 在调用时可以不用输入该位置的参数,而直接使用默认值;变化大的参数放在前,变化小的放在后作为默认参数,降低调用难度;调用含多个默认参数的函数时,可以写上参数名;如调用 def enroll(name, gender, age=6, city='Beiging'): 可以用enroll('Adam', 'M', city='Tianjin')
可变参数def calc(*numbers): 传入的参数个数时可变的,在参数前面加 1 个 * 号,参数接收到的将是一个 tuple;在 tuple/list 前加 1 个 *,可以将其以可变参数传入函数 calc(*[1,2,3])
关键字参数def person(name, age, **kw): 同理可变参数,在参数前面加 2 个_号,允许传入 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict;在 dict前加 2 个_ 可以将其以关键字参数传入函数 person(name, age, **kw)
命名关键字参数def person(name, age, *, city, job): 如果要限制关键字参数的名字,可以用命名关键字参数;命名参数需要以 * 分隔,其后视为命名关键字参数,如果函数定义了一个可变参数,可以不要 *,命名关键字参数可以给默认值

默认参数必须只想不可变对象
不可变对象减少了由于修改数据导致的错误,多任务环境同时读取不需加锁

# 错误写法
>>> def add_end(L=[]):
...     L.append('End')
...     return L
...
>>> add_end()
['End']
>>> add_end()
['End', 'End']

参数组合

顺序:必选参数 > 默认参数 > 可变参数 > 命名关键字参数 > 关键字参数

递归函数

一个函数在内部调用自己本身,就叫递归函数

函数调用是通过栈实现的,每进入一个函数调用,加一层栈锁,过多时会栈溢出

尾递归

把每一步的结果传递给递归函数,和循环的效果一样,栈不会增加;python 解释器没有对尾递归做优化,会栈溢出

汉诺塔

def move(n, a, b, c):if n == 1:print(a, '->', c)else:move(n-1, a, c, b)move(1, a, b, c)move(n-1, b, a, c)

2. 高阶函数

Higher-order function

变量可以指向函数 and 函数名也是变量 -> 函数可以接收另一个函数作为参数

其参数能够接收别的函数的函数,就是高阶函数

map/reduce

map()

接收两个参数,一个是函数(单个参数),一个是 Iterable 对象,map 将传入的函数依次作用在 Iterable 对象的每一个元素上,并把结果作为一个新的 Iterator 返回,注意 Iterator 是惰性的

>>> list(map(str, [1, 2, 3, 4, 5]))
['1', '2', '3', '4', '5']

reduce()

把一个函数(必须是两个参数)作用在一个序列上,reduce 把结果与下个元素做累计计算

reuce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
# str2int
from functools import reduceDIGITS = {'0': 0,'1': 1,'2': 2,'3': 3,'4': 4,'5': 5,'6': 6,'7': 7,'8': 8,'9': 9
}def char2num(c):return DIGITS[c]def str2int(s):return reduce(lambda x1, x2: x1 * 10 + x2, map(char2num, s))
# str2float
from functools import reduceDIGITS = {'0': 0,'1': 1,'2': 2,'3': 3,'4': 4,'5': 5,'6': 6,'7': 7,'8': 8,'9': 9
}def char2num(c):return DIGITS[c]def str2int(s):return reduce(lambda x1, x2: x1 * 10 + x2,map(char2num, [c for c in s if c != '.']))def str2float(s):return str2int(s) / (10**s[::-1].index('.'))
# str2float
def str2float(s):point = 0def to_float(i, c):nonlocal pointif not isinstance(c, int):point = 1return iif point == 0:return i * 10 + celse:point *= 10return i + c / pointreturn reduce(to_float, map(char2num, s))

nonlocal 关键字用来在函数或其他作用域使用外层(非全局)变量

filter

接收一个函数(单个参数)和一个序列,序列的每个元素作用于函数,返回 True/False 决定是否保留该元素

素数 - 埃氏筛选

def _odd_iter():n = 1while True:n += 2yield ndef _not_divisible(n):return lambda x: x % n > 0def primes():yield 2oi = _odd_iter()while True:n = next(oi)yield noi = filter(_not_divisible(n), oi)

sorted

接收一个 Iterable 对象,一个函数(形参:key,一个参数的函数),以及 reverse;key 作用与序列的每个元素,再对结果排序,reverse 表示是否反向排序,默认为 False

3. 函数式编程

面向过程程序设计

通过一层一层的函数调用,把复杂的任务分解成简单任务,这种分解称之为面向过程的程序设计,函数是面向过程编程的基本单元

Functional Programming

一种抽象程度很高的编程范式,纯粹的函数式编程语言(Lisp)编写的函数没有变量,只要输入确定,输出就是确定的(没有副作用)。允许使用变量的函数内部变量状态不确定,同样输入可能输出不同

Python 对函数式编程提供部分支持,其允许使用变量,不是纯函数式编程语言

返回函数

函数作为返回值
往往不需要立即执行的时候,可以使用返回函数的方式达到惰性计算的效果(lazy

闭包(Closure)
当返回函数时,相关参数和变量都保存在返回的函数中,这种程序结构成为闭包

def count():fs = []for i in range(1, 4):def f():return i*ifs.append(f)return fsf1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9

返回的函数引用了变量 i,但它并没有立刻执行,等到 3 个函数都返回时,它们引用的变量 i 已经变成了 3,因此最终结果都是 9

返回闭包时,返回函数不要引用任何循环变量,或者后续会发生变化的变量

def count():def f(j):def g():return j*jreturn gfs = []for i in range(1, 4):# f(i) 立即执行,因此 i 的当前值被传入 f()fs.append(f(i))return fs
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

添加多层函数,用执行外层函数将循环变量的值绑定到函数的参数中,可以绑定循环变量变化过程中的值

计数器(闭包)

def createCounter():def counter():n = 0while True:n += 1yield nc = counter()return lambda : next(c)
def createCounter():n = 0def counter():nonlocal nn += 1return nreturn counter

匿名函数

关键字 lambda 表示匿名函数,冒号前面的是参数表,冒号后面的是返回结果,不用写 return,只能有一个表达式

匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数

>>> f = lambda x: x*x
>>> f(5)
25

也可以把匿名函数当作一个函数的返回值返回

def build(x, y):return lambda x, y: x*x + y*y

装饰器

Decorator

在函数调用前后自动增加处理,不修改函数的定义,这种在代码运行期间动态增加功能的方式,即为 Decorator

import functoolsdef log(func):@functools.wraps(func)def wrapper(*args, **kwargs):print(f'call {func.__name__}():')return func(*args, **kwargs)return wrapper
def log(info):def decorator(func):@functools.wraps(func)def wrapper(*args, **kwargs):print(f'{info} {func.__name__}')return func(*args, **kwargs)return wrapperreturn decorator

调用 Decorator

@log
def now():print('2020-11-12')
now = log(now)
@log('execute')
def now():print('2020-11-12')
now = log('execute')(now)

functools.wraps(func) 的作用是将 wrapper 函数的 __name__ 改为被装饰函数对象的 __name__, 相当于:

wrapper.__name__ = func.__name__

Decorator 即在 面向对象(OOP)设计模式 中的 装饰模式,OOP 的装饰模式通过类的继承和组合实现,而 Python 可以直接从语法层面支持 decorator,也可以通过类实现

偏函数

Partial function

把一个函数的某些参数固定住(给这些参数设置默认值),返回一个新函数,以方便调用

偏函数仅仅是给参数设定了默认值,在调用新函数时是可以传入其他值给这些参数的

import functools
# 相当于
# kw = {'base': 2}
# int('1000000', **kw)
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1000000', base=10)
1000000
# 相当于
# args = [10]
# args.extend([5, 6, 7])
# max(*args)
>>> max2 = functools.partial(max, 10)
>>> max2(5, 6, 7)
10

创建偏函数时,实际接收的参数是:函数对象,*args / **kwargs


上一篇:「Python 基础」基础语法与高级特性
专栏:《Python 基础》

PS:感谢每一位志同道合者的阅读,欢迎关注、评论、赞!

相关内容

热门资讯

此时无声胜有声初中作文【通用... 此时无声胜有声初中作文 篇一随着科技的不断进步和社会的快速发展,人们的生活变得越来越喧嚣。嘈杂的声音...
我们是一家人初中作文600字... 我们是一家人初中作文600字 篇一家,是一个人生活的港湾;家,是一个人成长的摇篮。而对于我来说,家更...
我的执着初一作文(精彩6篇) 我的执着初一作文 篇一执着是一种坚持不懈的品质,它使我在初一的学习生活中取得了许多成就。正是这种执着...
外祖母-初一作文【最新5篇】 外祖母-初一作文 篇一外祖母是我最亲密的长辈,她是一个非常温柔和善良的人。每次我见到她,她都会给我一...
往事如风作文【优选5篇】 往事如风作文 篇一往事如风,岁月如梭。回首过去的时光,仿佛一切都已经过去,只留下了一抹淡淡的回忆。往...
游东沙古镇初一作文1000字... 游东沙古镇初一作文1000字 篇一初一的暑假,我随着家人来到了东沙古镇,这是一个有着悠久历史和独特魅...
捡蘑菇的作文七年级共70篇 捡蘑菇的作文七年级 第一篇雨后,天空一碧如洗,空气也格外清新。小白免皮皮和妈妈跨着竹篮迫不及待地到山...
我的初一生活作文(精选6篇) 我的初一生活作文 篇一初一,是我人生中一个全新的开始。离开了小学的校园,踏入了初中的大门,我怀着激动...
黑与白的初中议论文【经典5篇... 黑与白的初中议论文 篇一黑与白,是一对互补的色彩,代表了对立却又相互依存的存在。在日常生活中,我们常...
初中随笔作文400字【最新5... 初中随笔作文400字 篇一我的偶像每个人都有自己的偶像,他们可以是明星、运动员、作家等等。而我的偶像...
初一餐桌前的谈话作文500字... 初一餐桌前的谈话作文500字 篇一初一餐桌前的谈话今天是我初一的第一天,我很兴奋地回到家中。晚饭时,...
初一作文《假期见闻》(优选6... 初一作文《假期见闻》 篇一我的假期过得非常充实和有意义。在假期中,我参加了一次有趣的亲子旅行,还参加...
八年级作文(精彩6篇) 八年级作文 篇一:我的暑假计划暑假即将来临,我对这个假期充满了期待。我计划度过一个充实而有意义的暑假...
2017年春运火车票购票时间... 2017年春运火车票购票时间表 篇一春运是中国人民一年中最繁忙的出行季节之一,而购票则是春运期间备受...
初中作文题材万能素材积累【优... 初中作文题材万能素材积累 篇一标题:如何保护环境随着工业化和城市化的快速发展,环境问题越来越受到人们...
春天来了初一作文【推荐5篇】 春天来了初一作文 篇一春天来了,大地万物开始苏醒。初一的阳光明媚,温暖的春风轻拂着我们的脸庞,带给我...
老班长作文(优选6篇) 老班长作文 篇一回忆起初中时代,我心中最深刻的一个人就是我们班级的老班长。他是一个身材高大、目光炯炯...
原来我没懂【经典3篇】 原来我没懂 篇一在人生的旅途中,我们常常会因为一些事情或者一些人而感到困惑,迷失方向。不过,当我们经...
初中什么的我600字作文(经... 初中什么的我600字作文 篇一初中生活中的快乐与收获初中生活是人生中一个重要的阶段,对于每个学生来说...
原来这就是爱初一作文(实用6... 原来这就是爱初一作文 篇一我曾经以为爱是一种感觉,是一种浪漫的情怀。然而,随着我渐渐长大,我明白了爱...