当前位置: 首页 > news >正文

「Python 基础」函数与高阶函数

文章目录

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

相关文章:

「Python 基础」函数与高阶函数

文章目录1. 函数调用函数定义函数函数的参数递归函数2. 高阶函数map/reducefiltersorted3. 函数式编程返回函数匿名函数装饰器偏函数1. 函数 函数是一种重复代码的抽象方式,Python 内建支持的一种封装; 调用函数 调用一个函数,需要知道函数…...

DIV内容滚动,文字符滚动标签marquee兼容稳定不卡

marquee(文字滚动)标签 marquee简介 <marquee>标签,是成对出现的标签,首标签<marquee>和尾标签</marquee>之间的内容就是滚动内容。 <marquee>标签的属性主要有behavior、bgcolor、direction、width、height、hspace、vspace、loop、scrollamount、scr…...

SpringBoot_第五章(Web和原理分析)

目录 1&#xff1a;静态资源 1.1&#xff1a;静态资源访问 1.2&#xff1a;静态资源源码解析-到WebMvcAutoConfiguration 2&#xff1a;Rest请求绑定&#xff08;设置put和delete&#xff09; 2.1&#xff1a;代码实例 2.2&#xff1a;源码分析到-WebMvcAutoConfiguratio…...

4-2 Linux进程和内存概念

文章目录前言进程状态进程优先级内存模型进程内存关系前言 进程是一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源。一般来说&#xff0c;Linux系统会在进程之间共享程序代码和系统函数库&#xff0c;所以在任何时刻内存中都只有代码的一份拷贝。 进程状态…...

【微信小程序】计算器案例

&#x1f3c6;今日学习目标&#xff1a;第二十一期——计算器案例 ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;30分钟 &#x1f389;专栏系列&#xff1a;我的第一个微信小程序 计算器前言实现效果实现步骤wxmlwxssjs数字按钮事件处理函数计算按钮处理事…...

408 计算机基础复试笔记 —— 更新中

计算机组成原理 计算机系统概述 问题一、冯诺依曼机基本思想 存储程序&#xff1a;程序和数据都存储在同一个内存中&#xff0c;计算机可以根据指令集执行存储在内存中的程序。这使得程序具有高度灵活性和可重用性。指令流水线&#xff1a;将指令分成若干阶段&#xff0c;每…...

找出最大数-课后程序(Python程序开发案例教程-黑马程序员编著-第二章-课后作业)

实例6&#xff1a;找出最大数 “脑力大乱斗”休闲益智游戏的关卡中&#xff0c;有一个题目是找出最大数。本实例要求编写程序&#xff0c;实现从输入的任意三个数中找出最大数的功能。 实例分析 对于3个数比较大小&#xff0c;我们可以首先先对两个数的大小进行比较&#xff…...

Java——N叉树的层序遍历

题目链接 leetcode在线oj题——N叉树的层序遍历 题目描述 给定一个 N 叉树&#xff0c;返回其节点值的层序遍历。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&…...

【Kubernetes】第十八篇 - k8s 服务发现简介

一&#xff0c;前言 上一篇&#xff0c;介绍了阿里云 ECS 服务器重启后的环境修复&#xff1b; 本篇&#xff0c;介绍 k8s 服务发现&#xff1b; 二&#xff0c;服务发现简介 当 A服务依赖了 B服务&#xff0c;而 B服务的IP和端口未知&#xff08;或相对不固定&#xff09;&…...

Codeforces Round 856 (Div. 2) 最好ak的div2

最近几场的div2 E都是一个思路啊&#xff0c;代码大差不差的&#xff0c;感觉随便ak啊。 A. Prefix and Suffix Array 题意 给你前n−1n-1n−1个字符串前缀和后n−1n-1n−1个字符串后缀&#xff0c;判断原字符串是否是回文串 思路 相同长度的判断是否是对称的即可。 代码 B C…...

最新JVM技术: GraalVM,让你一文了解它的方方面面

1. 什么是GraalVM? GraalVM是一种开源的虚拟机平台,由Oracle公司开发。它支持多种编程语言,包括Java、JavaScript、Python、Ruby、R、C++等,旨在提高应用程序的性能和扩展性。 GraalVM通过提供即时编译器(Just-in-Time Compiler,JIT)和Ahead-of-Time(AOT)编译器来提…...

MySQL索引失效的场景

1.like 以%开头&#xff0c;索引无效&#xff1b;当like前缀没有%&#xff0c;后缀有%时&#xff0c;索引有效。 2.数据库表数据量过小 如果表的数据量非常小&#xff0c;则MySQL可能不会使用索引&#xff0c;因为它认为全表扫描的代价更小。 3.or语句前后没有同时使用索引 …...

Java - 对象的比较

一、问题提出 前面讲了优先级队列&#xff0c;优先级队列在插入元素时有个要求&#xff1a;插入的元素不能是null或者元素之间必须要能够进行比较&#xff0c;为了简单起见&#xff0c;我们只是插入了Integer类型&#xff0c; 那优先级队列中能否插入自定义类型对象呢&#xf…...

[算法]选择排序

目录 1、选择排序的实现 2、例子 3、代码实现 4、时间复杂度和空间复杂度 5、选择排序的缺点——不稳定性 1、选择排序的实现 选择排序就是每一轮选择最小的元素直接交换到左侧。这种排序的最大优势&#xff0c;就是省去了多余的元素交换。 2、例子 原始数组和选择排序的…...

dp模型——状态机模型C++详解

状态机定义状态机顾名思义跟状态有关系&#xff0c;但到底有什么关系呢。在实际解决的时候&#xff0c;通常把状态想成节点&#xff0c;状态的转换想成有向边的有向图&#xff0c;我们来举个例子。相信大家都玩过类似枪战的游戏&#xff08;没玩过的也听说过吧&#xff09;&…...

1.4 条件概率与乘法公式

1.4.1 条件概率在实际问题中&#xff0c;除了直接考虑某事件 B 发生的概率P(B)外,有时还会碰到这样的问题&#xff0c;就是“在事件A 已经发生的条件下,事件B 发生的概率”。一般情况下,后概率与前一概率不同&#xff0c;为了区别,我们常把后者称为条件概率&#xff0c;记为P(B…...

VITA/PYTHON/LUPA families

Image Sensor Group Top to Bottom Portfolio in Industrial Imaging Machine Vision • Factory automation and inspection • Robotic vision • Biometrics High-End Surveillance • Aerial Surveillance • Intelligent Traffic Systems (ITS) • Mapping Medical and Sc…...

ChatGPT概述:从模型训练到基本应用的介绍

ChatGPT概述&#xff1a;从模型训练到基本应用的介绍 目录 本文是对ChatGPT的由来、训练过程以及实际落地场景的解释&#xff0c;主要内容包括如下三个方面&#xff1a; 1、ChatGPT是什么 2、ChatGPT的原理 3、ChatGPT的思考 4、ChatGPT的应用 ChatGPT是什么 ChatGPT可能是近…...

C语言实现扫雷【详细讲解+全部源码】

扫雷的实现1. 配置运行环境2. 扫雷游戏的初步实现2.1 建立扫雷分布模块2.2 创建名为board的二维数组并进行棋盘初始化2.3 打印棋盘3. 接下来该讨论的事情3.1 布置雷3.2 排查雷3.3 统计坐标周围有几个雷4. 完整扫雷游戏的实现4.1 game.h4.2 game.c4.3 扫雷.c1. 配置运行环境 本游…...

Vue2.0开发之——购物车案例-Goods组件封装-商品名称和图片(46)

一 概述 循环渲染Goods组件为Goods组件封装title属性为Goods组件封装pic属性 二 循环渲染Goods组件 2.1 App.vue中导入Goods组件 import Goods from /components/Goods/Goods.vue2.2 App.vue中注册Goods组件 components: {Header,Goods}2.3 循环渲染每一个商品的信息 <…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...