函数的详细笔记
函数
就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用
函数定义
''' 定义函数 '''
# def 定义函数的关键字
# func 函数名字:要满不足标识符的命名规则
def func():
# 函数体
# 函数块下方用来书写我们的代码逻辑
print('人生苦短,我用python')
return 'python'
# 函数必须先声明在调用
# 函数名() 只有调用之后函数体里面的代码逻辑才会被执行
func()
''' 示例 - 计算1-100之间值的函数 '''
# 声明函数
def get_sum():
total = 0
for i in range(100):
total += i
print(total)
# 调用函数
get_sum()
函数返回值
程序运行到所遇到的第一个return即返回(退出def块),实现函数值的返回,不会再运行第二个return。返回时可附带一个返回值,由return后面的参数指定。
return 之后函数就结束了,不会再执行后续代码
''' 函数 return 的返回值'''
# 1. 将 `y = kx + b` 封装成一个函数,其中 `k=5` , `b=6` , 假设 `x=5`
# 2. 在函数下方调用线性方程函数,打印结果
def f(x):
y = 5 * x + 6
print('我还没有遇到return')
return y
print('我已经遇到过return')
# 是用于返回数据
# 函数和外界是数据不互通的 假设函数外部需要获取到函数内部的值,只能通过 'return' 返回这个值才可以得到
# 当函数没有return返回值结果, 在调用函数的时候打印结果就会是None
# 函数一旦遇到return, 就会立马结束整个函数的执行
print(f(7))
''' 示例 '''
# 利用函数, 求两个数的最大值
def max_num(num1,num2):
if num1 > num2:
return num1 # 函数一旦执行到了return返回值会立马结束整个函数
else:
return num2
print(max_num(8,7))
''' 示例 '''
def sum_test(n):
sum = 0
for x in range(1, n + 1):
sum += x
return sum
print(sum_test(10)) # 55
''' 返回值形式 '''
# 1.无参数,无返回值 他是没有任何作用的
def f():
y = 5 * 6 + 7
# 2. 无参数,有返回值
def f(): # 被定死了 没有任何复用性可言
y = 5 * 6 + 7
return y
# 3.有参数,无返回值
def f(x):
y = 5 * x + 7 # 函数内部的无法传递给函数外部 他也是没有任何作用
# 4.有参数,有返回值 最常用的
def f(x):
y = 5 * x + 6
return y
函数参数
位置参数
Python 处理参数的方式要比其他语言更加灵活。其中,最熟悉的参数类型是位置参数,传入参数的值是按照顺序依次复制过去的。
# 根据形式参数的位置传递的参数, 叫做位置参数, 一一对应的关系
def f(x, k, b):
y = k * x + b
print(x)
print(k)
print(b)
return y
# print(f(1,4,5))
print(f(7,6,9))
'''
需求 : y = k * x +b 中 `k` 与 `b` 也不固定
'''
def f(x, k, b):
y = k * x + b
print(y) # 31
f(5, 5, 6)
'''
尽管这种方式很常见,但是位置参数的一个弊端是必须熟记每个位置的参数的含义。在调用函数 `f()` 时误把最后一个参数当作第一个参数,会得到完全不同的结果
'''
''' 示例 '''
# 利用函数,求两个数的最大值
def max_num(num1, num2): # 在定义函数的时候传递的参数叫做形式参数,没有偶实际意义的,只是用于占位
if num1 > num2:
max_nums = num1 # 最大值
else:
max_nums = num2
return max_nums
# 调用函数
print(max_num(1, 3)) # 实际参数,如果函数定义的时候设置了参数,那么函数调用时候一定要进行传参,数量要一致
关键字参数
# 为了避免位置参数带来的混乱,调用参数时可以指定对应参数的名字,
# 甚至可以采用与函数定义不同的顺序调用
def f(x, k, b):
y = k * x + b
print(x)
print(k)
print(b)
return y
# print(f(x=1,k=4,b=5))
print(f(k=5,x=5,b=6))
# 也可以把位置参数和关键字参数混合起来。首先,实例化参数 ,然后对参数使用关键字参数的方式
def f(x, k, b):
print("x:{} k:{} b:{}".format(x, k, b)) # x:5 k:5 b:6
y = k * x + b
return y
f(5, k=5, b=6)
# 如果同时出现两种参数形式,首先应该考虑的是位置参数
''' 位置参数和关键字参数进行混用 '''
def f(x, k, b):
y = k * x + b
print(x)
print(k)
print(b)
return y
print(f(8, k=6, b=9))
# #每个参数只能接受一个
print(f(8, x=7, k=6))
# 如果在进行位置参数和关键字参数的混用 位置参数必须写在关键字参数的前面
print(f(x=7, 4, b=5)) # 报错
默认参数
''' 默认参数 '''
# 在定义函数的时候, 设置了参数的值, 那么就叫做默认参数
def f(x=4, k=7, b=5): # 默认参数 位置参数必须写在关键字参数的前面
print(x)
print(k)
print(b)
y = k * x + b
return y
print(f())
""" 修改我的默认参数 """
# 通过位置参数进行修改 会优先使用位置参数
print(f(9, 8, 7))
# 别人有我就使用别人的 别人没有我就使用自己的
print(f(9))
# 通过关键字参数进行修改 优先使用关键字参数
print(f(x=7, k=9, b=6))
print(f(k=9)) # 别人有我就使用别人的 别人没有我就使用自己的
print(f())
# 混合修改
print(f(7, k=9, b=7))
不确定长度参数
*args
# 用 * 收集位置参数
# int * 特殊符号 有特殊的作用, 在定义函数的括号里面,用于收集所有的位置参数
# 在输出 或者是运行代码的过程中 是解包 包:元组、列表、迭代器、生成器
def print_args(*args):
# * 解包的标志
print('位置参数的类型:', type(args))
print('位置参数的内容:', args)
# *args 不定长参数 接受所有传进来的位置参数 <class 'tuple'> 元组
def get_num(*args):
print(args)
print(type(args))
total = 0
for i in args:
total += i
return total
print(get_num(70,80,60,40,50,50,60,40,58))
**kwargs
使用两个星号可以将参数收集到一个字典中,参数的名字是字典的键,对应参数的值是字典的值
# ** kwargs 接受所有传进来的关键字参数 <class 'dict'> 字典类型
def get_nums(**kwargs):
print(kwargs)
print(type(kwargs))
for i in kwargs.keys():
print(i)
return kwargs
print(get_nums(a=1,b=6,c=7))
''' 示例 '''
def print_kwargs(*arg, **kwargs):
""" args为关键字元组 kwargs为双元关键字元组 """
print('位置参数:', arg)
print('关键字参数:', kwargs)
"""总结"""
# 函数的参数: 函数可以根据传入的不同的参数值得到不同的结果
# 返回值: 用于沟通函数内外数据交互的唯一桥梁
# 函数的复用性: 在任意的代码逻辑中, 哪里需要执行函数逻辑, 就可以在哪里掉调用
函数作用域
''' 函数作用域 '''
num = 10 # 全局变量
def func():
# global 声明变量操作的是全局变量,不建议大家随便修改的
global num
num = 20 # 局部变量
return num
result = func() # 就是函数内部 num
print(result)
print(num)
# 如果想看2个变量引用的是不是同一对象,可以使用 id 函数,如果id一样就表示引用的同一个对象
print(id(result))
print(id(num))
# 如果变量名一样,但是 id 地址不一样,那么他还是2个不同的变量
交换变量值
''' 交换变量 '''
''' 方法一 '''
# 需求:有变量`a = 10`和`b = 20`,交换两个变量的值。
a = 10
b = 20
a = 20
b = 10
print(a)
print(b) # 这种方法不建议
# 这种方法是不行
a = b # 20就已经保存到a里面去了
b = a # b = 20
print(a)
print(b)
# 通过第三者的介入
c = None # 他就是一个空的对象 让我的c变成一个空的容器
c = a # # 将a 的数据保存到c里面去
# print(c)
a = b # 将我们的b的值传给我们的a
# print(a)
b = c # 我们的这个c保存着我们a的值
print(a)
print(b)
a = 10
b = 20
''' 方法二 '''
# 可以通过同时赋值,进行交换
# a,b = 10,20
# print(a)
# print(b)
a, b = b, a
print(a)
print(b)
lambda函数
如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化。
- lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
- lambda表达式能接收任何数量的参数但只能返回一个表达式的值
''' lambda 函数 '''
# 需求:函数 返回值100
def func1():
return 100
print(func1())
# 使用lambda代替(匿名函数)
# : 冒号的左边是参数
# : 冒号的右边是返回值
func = lambda: 100
print(func())
# 在默认情况下lambda函数没有名字
# 但是可以用变量接受匿名函数, 这个变量就相当于函数名
# 只能写简单的函数逻辑, 稍微复杂一点的函数逻辑都不支持匿名函数
# 需求:计算任意两个数字的累加和
def add(a, b):
return a + b
print(add(1, 5))
# 通过lambda 简化
# 冒号的左边是我们的参数,冒号的右边是返回值结果
fun1 = lambda a, b: a + b
print(fun1(6, 5))
''' lambda 参数分类 '''
# 无参数
fun = lambda: 200
print(fun())
# 一个参数
fun1 = lambda a: a
print(fun1(6))
# 3.默认参数(是在定义函数的时候就已经给参数进行了关键字的赋值)
fun3 = lambda a, b, c=100: a + b + c
# print(fun3(2,3))
print(fun3(3, 5, 6)) # 传递过去的值会覆盖掉默认参数的值
# 4.位置参数
fun4 = lambda a, b: a - b
print(fun4(5, 7))
# 5.关键字参数
fun5 = lambda a, b: a + b
print(fun5(a=6, b=6))
# 6.可变参数 #args 用于接受位置参数
fun6 = lambda *args: args
print(fun6(1, 4, 5, 6, 7, 8, 9, 9)) # 返回的是一个元组类型
# 7. 可变参数:**kwargs 用于接受关键字参数
fun7 = lambda **kwargs: kwargs
print(fun7(a=8, b=7, c=9)) # 返回的是一个字典
# 8.进行混用 要带括号
fun8 = lambda *args, **kwargs: (args, kwargs)
print(fun8(1, 3, 4, a=6, b=7))
''' 示例1 - 带判断的lambda'''
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
''' 示例2 - 列表数据按字典 key 的值排序 '''
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)
''' 不定长参数 '''
"""
我需要统计班级中每个人的成绩总和
(我不知道这个班有多少人)
"""
# 假设他有4个人
def get_num(re1, re2, re3, re4):
total = re1 + re2 + re3 + re4
return total
print(get_num(80,80,90,92))
# *args 不定长参数 接受所有传进来的位置参数 <class 'tuple'> 元组
def get_num(*args):
print(args)
print(type(args))
total = 0
for i in args:
total += i
return total
print(get_num(70,80,60,40,50,50,60,40,58))
# ** kwargs 接受所有传进来的关键字参数 <class 'dict'> 字典类型
def get_nums(**kwargs):
print(kwargs)
print(type(kwargs))
for i in kwargs.keys():
print(i)
return kwargs
print(get_nums(a=1,b=6,c=7))
''' 函数作用域 '''
num = 10 # 全局变量
def func():
# global 声明变量操作的是全局变量,不建议大家随便修改的
global num
num = 20 # 局部变量
return num
result = func() # 就是函数内部 num
print(result)
print(num)
# 如果想看2个变量引用的是不是同一对象,可以使用 id 函数,如果id一样就表示引用的同一个对象
print(id(result))
print(id(num))
# 如果变量名一样,但是 id 地址不一样,那么他还是2个不同的变量
''' 函数内部调用 '''
def fun1():
print('我是func1的内部') # 第二步
def func2():
fun1() # 第一步
print('我是func2的内部') # 第三步
print(func2())
案例 - 银行利息函数
"""
复利公式:s = p(1 + i)^n
s 是本金 + 利息
p 本金
i 利率
n 投资年限
余额宝 兴全添利宝 年化 2.5610%
假设本金(principal)10000
1、请问分别存 5年 10年 15年 20年后 本金利息共多少
2、如果利率(interest)变成 6% 分别存 5年 10年 15年 20年后 本金利息共多少
3、如果本金变成 20000,利率不变 分别存 5年 10年 15年 20年后 本金利息共多少
"""
def f2(p,i,n):
s = p * (1 + i) ** n
return s
# 调用执行
# 本金
principal = 10000
# 利率
interest = 2.5610/100
# 1.请问分别存 5年 10年 15年 20年后 本金利息共多少
print(f2(principal,interest,5))
print(f2(principal,interest,10))
print(f2(principal,interest,15))
print(f2(principal,interest,20))
# 2、如果利率(interest)变成 6% 分别存 5年 10年 15年 20年后 本金利息共多少
principal = 10000
interest = 6/100
print(f2(principal,interest,5))
print(f2(principal,interest,10))
print(f2(principal,interest,15))
print(f2(principal,interest,20))
# 3、如果本金变成 20000,利率不变 分别存 5年 10年 15年 20年后 本金利息共多少
principal = 20000
interest = 6/100
print(f2(principal,interest,5))
print(f2(principal,interest,10))
print(f2(principal,interest,15))
print(f2(principal,interest,20))
案例 - 函数实现登录功能
"""
定义一个函数, 实现登录的功能
要求: 现在有用户名(user_name) 密码(password) 两个变量
如果用户输入正确的用户名和密码, 提示 "登录成功"
如果用户输入错误的用户名和密码, 提示 "用户名或密码输入错误"
如果用户输入三次错误, 提示 "您输入错误的次数过多,登录异常", 退出函数运行
提示: 循环 + 逻辑判断
"""
user_name = 'zeyan' # 全局变量
password = '123456'
# 叫做全名变量,在函数内部是可以使用,但是如果要修改,就需要全局声明 global
# 在我自己不知道要输入多次的情况下 while True 和 break 进行跳出
"""请在下方实现代码"""
a = 10
def login():
s = 0
while True:
user = input('请输入你的账号:')
pwd = input('请输入你的密码:')
if user == user_name and pwd == password:
print('登录成功')
# break
return # 如果函数遇到 return 整个函数会停止执行
else:
global a # 先声明
a += 10 # 后修改
print('用户名和密码输入错误')
s += 1 # 用于统计输入错误的次数
print('输入错误的次数', s)
if s <= 3:
print('您输入错误的次数过多,登录异常')
break
案例 - 函数冒泡排序
冒泡排序(冒泡排序)也是一种简单的简单列访问排序。它重复地走过去要排序的数,一次比较两个元素,如果他们的顺序错误让他们交换过来。走访数工作列的是重复地进行到那时已经没有再需要交换了,该算法的名字会因为越过元素会来交换慢慢地“浮”到数列的排序。
''' 冒泡排序 '''
# 需求: 任意给定一组序列数字,
# 比如 [3, 38, 44, 5, 47, 15, 36, 26],
# 将序列从小到大排列。(不能使用python函数解决)sort很简单
# 如果是 升序排列 左边的数比右边大 那么他们2个就交换位置 如果左边的数比右边小 就不动
# 升序排列
def get_num(arr):
n = len(arr) # 列表元素有多少个他就会比较多少次 轮次
for i in range(n): # 01234567
for j in range(0,n-1):
if arr[j] > arr[j+1]: # 通过下表取值判断
arr[j],arr[j+1] = arr[j+1],arr[j] # 左边的数比右边大,进行位置交换
# print(arr)
return arr
print(get_num([3, 38, 44, 5, 47, 15, 36, 26]))
递归
递归是一种编程思想,应用场景:
- 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;
- 在后续的算法课程中,很多算法都离不开递归,例如:快速排序
案例 - 递归函数
''' 示例 - 递归函数 '''
# 需求:给定一个数字, 求 1 到这个数字中所有数字的和
# 3 3 + 2 + 1
# 5 5 + 4 + 3 + 2 + 1
# 所谓递归 本质就是自己调用自己
import sys # 内置模块
sys.setrecursionlimit(2000) # 设置限制的递归次数
def fun1(a):
print(a)
if a == 1:# 设置递归的出口
return 1 # return 遇到他函数终止 并且让fun1(1)返回1
result = a + fun1(a - 1) # fun1()代表调用函数
# result = 5 + fun1(4) fun1(4)会再去调用一次 result = 4 + fun1(4 - 1)
# result = 5 + 4 + fun1(3) fun1(3) 再去调用一次 result = 3 + fun1(3 - 1)
# result = 5 + 4 + 3 + fun1(2) 就会趋向于一个负的无穷大 fun1(2) 2 +fun1(1)
# result = 5 + 4 + 3 + 2 + fun1(1)
# result = 5 + 4 + 3 + 2 + 1
return result
# print(fun1(1000))
print(fun1(5))
# 我们的递归函数如果没有特别的定义 ,那么最多递归1000次
''' 示例 - 累乘 '''
# 需求 : 给定一个数字,求1到这个数字中所有数字的积
# 3 3 * 2 * 1
# 5 5 * 4 * 3 * 2 * 1
def func2(num):
if num == 1: # 设置递归出口
return 1 # return 函数遇到他会停止
result = num * func2(num-1)
return result
print(func2(5))
案例 - 斐波那契数列
"""
斐波那契数列(Fibonacci sequence),
又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,
指的是这样一个数列:1、1、2、3、5、8、13、21、34、……n
#自己本身的值是等于前2个值之和
在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
"""
# 需求求递6个斐波那契数
def fib(num): # num 表示第几个斐波那契数
if num == 1 or num == 2:
return 1
result = fib(num - 1) + fib(num - 2)
# num = 6 result = fib(5) + fib(4) 会执行result = fib(num - 1) + fib(num - 2)
# result = fib(4) + fib(3) + fib(4)
# result = fib(3) + fib(2) + fib(3) + fib(3) + fib(2)
# result = fib(2) + fib(1) + fib(2) + fib(2) + fib(1) + fib(2) + fib(1) + fib(2)
# result = 8
return result
print(fib(6))
案例 - 三目运算符
# 需求 求2个数的最大值
# 三元运算又叫三目运算符
num1 = int(input('请输入第一个数:'))
num2 = int(input('请输入第二个数:'))
if num1 > num2:
num_max = num1
else:
num_max = num2
print(num_max)
# 如果if后面的表达式布尔结果是True哪么就返回if左边的值,反之则返回else右边的值
max_num = num1 if num1 > num2 else num2
print(max_num)
fun = lambda a, b: a if a > b else b
print(fun(7, 9))
案例 - lambda 排序问题
import asynchat
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]
a = [1, 7, 4, 5, 6]
print(a.sort())
print(students.sort())
print(students)
def func1(x):
print('这是函数内部打印的传进来的列表中的每一个数据: ', x)
return x['age']
# key参数后指定一个函数
# 会把 students 列表每一个数据传入到指定的函数当中作为实际参数 在底层会便利传递给x
# 默认升序
students.sort(key=func1)
print(students)
# 使用lambda 如果要降序的话 reverse= True
students.sort(key=lambda x: x['age'], reverse=True)
print(students)
内置高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式
map()
map
函数接收的是两个参数,一个是函数名,另外一个是序列,其功能是将序列中的数值作为函数的参数依次传入到函数值中执行,然后再返回到列表中。返回值是一个迭代器对象
# map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
# map(函数规则, 序列)
list1 = [1, 3, 4, 5]
def func(x):
return x * 3
result = map(func, list1)
print(list(result)) # [3, 9, 12, 15]
# lambda 替换
result1 = map(lambda x: x * 3, list1)
print(list(result1)) # [3, 9, 12, 15]
''' 示例 '''
def func(x):
return x ** 2
map(func, [2, 3, 4, 5])
print(map(func, [2, 3, 4, 5])) # <map object at 0x00000111F07E3DF0>
print(type(map(func, [2, 3, 4, 5]))) # <class 'map'>
res = map(func, [2, 3, 4, 5])
for i in res:
print(i) # 4 9 16 25
print(list(map(func, [2, 3, 4, 5]))) # [4, 9, 16, 25]
''' 示例 - 高阶函数map一般 和 匿名函数 lambda联合使用 '''
calc1 = lambda x: x ** 2
print(calc1(2)) # 4
calc2 = lambda x, y: x * y
print(calc2(3, 5)) # 15
print(list(map(calc1, [6, 7, 8, 9]))) # [36, 49, 64, 81]
# 或 # 两者是一样的
print(list(map(lambda x,: x ** 2, [6, 7, 8, 9]))) # [36, 49, 64, 81]
print(list(map(calc2, [2, 3, 4, 5], [6, 7, 8, 9]))) # [12, 21, 32, 45]
# 或 # 两者是一样的
print(list(map(lambda x, y: x * y, [2, 3, 4, 5], [6, 7, 8, 9]))) # [12, 21, 32, 45]
''' 示例 - 利用map批量检测用户名是否符合规范=> username符合规范, username不符合规范'''
lst = ["username", "a123", "Y_78ju", "23hu", "was23_67hu"]
import re
def func1(x):
if re.findall(r"^[a-zA-Z_][0-9a-zA-Z_]{5,17}$", x):
return f"{x}符合规范"
else:
return f"{x}不符合规范"
print(list(map(func1, lst))) # ['username符合规范', 'a123不符合规范', 'Y_78ju符合规范', '23hu不符合规范', 'was23_67hu符合规范']
print(list(
filter(lambda x: re.findall(r"^[a-zA-Z_][0-9a-zA-Z_]{5,17}$", x), lst))) # ['username', 'Y_78ju', 'was23_67hu']
zip()
# zip() : 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
''' 组包 '''
a = [1, 2, 3, 4]
b = ('aa', 'bb', 'cc', 'dd')
result = zip(a,b)
print(result)
# zip能够将指定的序列按照索引进行一一的组合
print(list(result))
# 长度不一样的序列,他会以最短的序列进行组合
a = [1, 2, 3, 4]
b = ('aa', 'bb', 'cc')
result = zip(a,b)
print(list(result))
''' 解包 '''
res1 = [1, 2, 3]
res2 = 'abcd'
res3 = ('77', 88, 99)
# 按照索引位置进行一一解包 他会以最短的序列进行解包 不会改变原有数据类型
for a,b,c in zip(res1,res2,res3):
print(a)
print(b)
print(type(c))
''' 案例 '''
"""
假设有以下地址:
https://www.bbsmax.com/A/?user=7001&id=1305
https://www.bbsmax.com/A/?user=7002&id=1306
https://www.bbsmax.com/A/?user=7003&id=1307
https://www.bbsmax.com/A/?user=7004&id=1308
https://www.bbsmax.com/A/?user=7005&id=1309
https://www.bbsmax.com/A/?user=7006&id=1310
https://www.bbsmax.com/A/?user=7007&id=1311
https://www.bbsmax.com/A/?user=7008&id=1312
https://www.bbsmax.com/A/?user=7009&id=1313
https://www.bbsmax.com/A/?user=7010&id=1314
观察以上地址规律, 将以上规律用循环构建出来
"""
# 第一种方法
user = range(7001, 7011)
id_s = range(1305, 1315)
for user_1, id_1 in zip(user, id_s):
print(f'https://www.bbsmax.com/A/?user={user_1}&id={id_1}')
# 第二种方法
user1 = 7000
id_s1 = 1304
for j in range(1, 11): # 12345678910
# print(j)
print(f'https://www.bbsmax.com/A/?user={user1 + j}&id={id_s1 + j}')
reduce()
reduce函数也是一个参数为函数,另一个参数为可迭代对象 Iterable Object(eg: list列表)。,其返回值为一个值而不是迭代器对象
,故其常用与叠加、叠乘
等
# reduce() : 函数会对参数序列中元素进行累积。
# reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算
import functools # 内置模块
# reduce(func, 序列) 根据指定的函数规则做运算
list1 = [1, 2, 3, 4, 5]
def fun(a, b):
return a + b
result = functools.reduce(fun, list1)
print(result) # 15
''' 示例 '''
from functools import reduce
def func(x, y):
return x * 10 + y
reduce(func, [3, 4, 5, 6])
# func(3,4) = 3*10+4 = 34
# func( func(3,4),5) = func(34, 5) = 34*10+5 = 345
# func( func( func(3,4), 5), 6) = 345*10 +6 = 3456
''' 示例 '''
from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return DIGITS[s]
return reduce(fn, map(char2num, s))
filter()
filter函数也是接收一个函数和一个序列的高阶函数,其主要功能是过滤
。其返回值也是迭代器对象,例如:<filter object at 0x000002042D25EA90>
# filter(func, lst) :函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。
# filter(func, 序列)
list1 = [1, 2, 3, 4, 5, 6]
def fun(x):
return x % 2 == 0 # 用于筛选偶数
result = filter(fun, list1) # 会默认把学列的元素全部遍历
print(list(result)) # [2, 4, 6]
''' 示例 '''
names = ["Alex", "amanda", "xiaowu"]
# filter函数机制
def filter_test(func, iter):
names_1 = []
for i in iter:
if func(i): # 传入的func函数其结果必须为bool值,才有意义
names_1.append(i)
return names_1
# filter_test函数
print(filter_test(lambda x: x.islower(), names)) # ['amanda', 'xiaowu']
# filter函数
print(list(filter(lambda x: x.islower(), names))) # ['amanda', 'xiaowu']
sorted()
Python内置的sorted()函数就可以对list进行排序
print(sorted([36, 5, -12, 9, -21])) # [-21, -12, 5, 9, 36]
# sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序
# key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序
print(sorted([36, 5, -12, 9, -21], key=abs)) # [5, 9, -12, -21, 36]
# 要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True
print(sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)) # ['Zoo', 'Credit', 'bob', 'about']
min/max/sum/len
"""
编写一个函数,计算传入的数值序列的最大值、最小值和平均值,并一起返回,然后调用该函数
"""
# 方法一
def get_num(arr):
""" 求最小值 """
min_num = arr[0] # #假设他是最小
for i in arr:
if i < min_num:
min_num = i
""" 求最大值 """
max_num = arr[0] # 假设他是最大
for j in arr:
if j > max_num:
max_num = j
""" 求平均数 """
total = 0
for k in arr:
total += k # 求序列总和
average_num = total / len(arr)
return max_num, min_num, average_num
# 方法二
def count_aray(arr):
min_num = min(arr) # 用于取最小值
max_num = max(arr) # 用于取最大值
average_num = sum(arr) / len(arr) # sum 求和,len 长度
return max_num, min_num, average_num
print(get_num([3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]))
print(count_aray([3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]))
案例 - lambda函数去除功能
"""
把列表中所有人名的*去掉,比方: Tenc*ent--> Tencent
"""
name = ['Tenc*ent', 'Zhi*hu', 'Bai*du']
# 代码中要用到lambda函数
"""请在下方编辑代码"""
# 用于替换普通函数功能的
# 只能用于书写一些简单的代码逻辑
# map() 将传入的函数变量 func 作用到 list 变量的每个元素中,并将结果组成新的列表
def func(x):
print(x)
s = x.replace('*', '')
return s # 把数据返回给函数外部,实现数据的共享
result = map(func, name) # map是会将序列里面的每个元素传递给我们定义好的函数
print(list(result))
# 用到 lambda函数
result1 = map(lambda x: x.replace('*', ''), name)
print(list(result1))