「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:感谢每一位志同道合者的阅读,欢迎关注、评论、赞!

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...