高阶函数
1.函数作为变量
python 中声明函数就是声明一个类型为function的变量,函数名就是变量名
普通变量能做的事情函数都可以做
def fun1():
print('函数1')
return 100
print(type(fun1))
2.普通变量能做的事情函数都可以做
1)一个变量可以给另一个变量赋值
a = 100
b = a
print(b, b + 10)
def fun2():
print('函数2')
return 200
b2 = fun2
print(type(b2), b2())
# 2)修改变量的值
fun3 = 100
# fun3() TypeError: 'int' object is not callable
# 3)变量作为序列元素
a = 10
list1 = [a, 100, 'abc']
print(list1)
list2 = [fun2, fun2(), 10]
print(list2[0]())
# 4)变量作为函数的参数
def func3(x):
print('函数5:', x)
a = 100
func3(a)
func3(fun2)
3.将函数作为函数的参数 - 实参高阶函数
def fun4(x):
y = x()
return y
re = fun4(fun2)
print(re)
2.系统的实参高阶函数
列表.sort()、sorted()、max()、min()都是实参高阶函数,因为这四个函数中都有一个参数key,要求是一个函数
nums = [10, 89, 78, 7]
nums.sort(reverse=True)
print(nums)
1)排序方法:参数key要求是一个函数,作用是用来定制排序规则(默认按元素的大小从小到大或从大到小)
参数key的要求
a.key是一个函数
b.函数中有且只有一个参数,这个参数指向的是序列中的每个元素
c.函数需要一个返回值,这个返回值就是排序的时候比较大小的对象
# def func_key(item):
# return item % 10
# nums.sort(key=func_key)
nums.sort(key=lambda x: x % 10)
print(nums)
students = [
{'name': '小明', 'age': 18, 'score': 90},
{'name': '小花', 'age': 23, 'score': 78},
{'name': '小兰', 'age': 17, 'score': 65},
{'name': '小红', 'age': 30, 'score': 89}
]
students.sort(reverse=True, key=lambda item: item['score'])
print(students)
students.sort(key=lambda item: item['score'] + item['age'])
print(students)
# 2)max、min直接比较元素的大小求出最大最小值
nums = [100, 39, 51, 62, 58]
max1 = max(nums)
print(max1)
max2 = max(nums, key=lambda i: i % 10)
print(max2)
3)max函数的原理
def max1(seq, key=None):
t_seq = list(seq)
t_max = t_seq[0]
if not key:
for item in t_seq[1:]:
if item > t_max:
t_max = item
else:
for item in t_seq[1:]:
if key(item) > key(t_max):
t_max = item
return t_max
print(max((10, 9, 8, 67), key=lambda item: item % 10))
print(max1((10, 9, 8, 67), key=lambda item: item % 10))
返回值高阶函数
1.变量可以作为函数的返回值
def sum1(x, y):
t = x + y
return t
print(sum1(10, 20))
# 函数作为函数的返回值 - 返回值高阶函数
# func1就是一个返回值高阶函数
def func1():
def func2():
print('函数2')
return func2
print(func1())
func1()()
print(func1()())
2.闭包 - 函数1中声明了一个函数2,并且在函数2中使用了函数1的数据,那么这个函数1就是一个闭包
闭包的特点:闭包函数中的数据不会因为函数调用结束而销毁
def func3():
a = 10
def func4():
print(a)
return func4
t = func3()
t()
# 面试题1:
list1 = []
for i in range(5):
list1.append(lambda x: x*i) # 声明函数不会执行函数体,所以list1中五个函数都是一样的
# i = 4
print(list1[1](2), list1[2](2), list1[3](2))
# 面试题2
def func2(seq=[]):
seq.append(10)
return seq
print(func2())
print(func2())
# 练习:写出打印列表
list3 = [1, 2]
def func3(seq=list3):
seq.append(10)
return seq
func3()
list3.append(100)
print(func3())
装饰器
1.什么是装饰器
装饰器本质是一个函数 = 返回值高阶函数 + 实参高阶函数 + 糖语法
装饰器是python的三大神器之一:装饰器,迭代器,生成器
作用:给已经写好的函数添加功能
# 给函数添加一个功能:统计函数的执行时间
# 方法一:在每个需要添加功能的函数中加入相应的代码
def sum_w(x, y):
start = time.time() # 获取当前时间
sum1 = x+y
print(sum1)
end = time.time()
print('函数执行时间:%fs' % (end - start))
sum_w(100, 200)
def factorial(n):
start = time.time()
num1 = 1
for num in range(1, n+1):
num1 *= num
print('%d的阶乘是:%d' % (n, num1))
end = time.time()
print('执行时间是:%fs' % (end-start))
factorial(5)
# 方法二:
# 注意:这个add_time只能给没有参数的函数添加统计时间的功能
def add_time(fn):
# fn = func1
start = time.time()
fn()
end = time.time()
print('函数执行的时间:%fs' % (end - start))
def add_time2(fn, *args, **kwargs):
start = time.time()
fn(*args, **kwargs)
end = time.time()
print('函数执行的时间:%fs' % (end - start))
def func1():
print('===========')
print('-----------')
def func2():
print('你好世界')
print('你好python')
def func3(x, y):
print('%d+%d=%d' % (x, y, x+y))
add_time(func1)
add_time(func2)
add_time2(func1)
# func3(10, 20)
add_time2(func3, 10, 20)
2.装饰器
无参装饰器
def 函数名1(参数1):
def 函数名2(*args, **kwargs):
参数1()
新功能对应的代码段
return 函数名2
说明:
函数名1 - 装饰器的名字 - 一般根据需要添加的功能命名
参数1 - 需要添加功能的函数,一般命名fn
函数名2 - 随便命名, 可以用test
def add_time3(fn):
def test(*args, **kwargs):
start = time.time()
fn(*args, **kwargs)
end = time.time()
print('函数执行的时间:%fs' % (end - start))
return test
@add_time3
def func5():
print('你好吗')
func5()
# 练习:给所有返回值是整数的函数添加功能;返回值以16进制形式的数据返回
def hex_1(fn):
def test(*args, **kwargs):
a = fn(*args, **kwargs)
if isinstance(a, int):
return hex(a)
return a
return test
@hex_1
def t_sum(x, y):
return x+y
print(t_sum(10, 20))
解包操作
# 1.解包:在容器型数据类型前加*或者**可以对容器进行解包
# 注意: **只能放在字典的前面
list1 = [10, 20, 30]
print(*list1) # -> 10 20 30
def func1(x, y, z):
print(x, y, z)
func1(*list1)
# 练习:写一个函数,可以对多个数据进行不同的运算
def sum_1(*nums):
num1 = 0
for x in nums:
num1 += x
return num1
def sub_1(*nums):
num1 = nums[0]
for x in nums[1:]:
num1 -= x
return num1
def operation(char, *nums):
if char == '+':
return sum_1(*nums)
elif char == '-':
return sub_1(*nums)
print(operation('-', 9, 90, 80, 7, 60))
# 2)**是将字典解包
dict1 = {'x': 100, 'y': 200} # **dict1 == x==100,y==200;*dict=x,y
print(*dict1)
"""
装饰器 - 用一个函数去装饰另外一个函数或类为其提供额外的功能
"""
import random
import time
from functools import wraps
def record_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__}执行时间: {end - start}秒')
return result
return wrapper
@record_time
def download(filename):
"""下载"""
print(f'开始下载{filename}')
time.sleep(random.random() * 6)
print(f'{filename}下载完成')
@record_time
def upload(filename):
"""上传"""
print(f'开始上传{filename}')
time.sleep(random.random() * 8)
print(f'{filename}上传完成')
# download = record_time(download)
print(download.__name__, upload.__name__)
download('Python从入门到住院.pdf')
# 取消掉装饰器
download = download.__wrapped__
download('北京有点冷.avi')
upload('数据库从删库到跑路.pdf')
迭代器
1.什么是迭代器(iter)
迭代器也是python提供的容器型数据类型
迭代器存储数据的特点:一个迭代器可以存储多个数据,如果要获取元素必须将元素从迭代器中取出,
取一个少一个,取出来的数据不能再添加到迭代器中
2.将数据存入迭代器:1)将别的序列转换成迭代器 2)创建生成器
list1 = [10, 20, 30, 40]
iter1 = iter(list1)
print(iter1)
iter2 = iter('hello')
print(iter2)
3.获取迭代器中的元素
迭代器中的元素不管通过什么方式取出来了,那么这个元素在迭代器中就不存在了
1)获取单个元素
next(迭代器) -> 取出迭代器中最前面的元素
print(next(iter1))
print(next(iter1))
print(next(iter1))
print(next(iter1))
# 2)遍历 - 一个一个的取所有元素
for x in iter2:
print('x', x)
print('================================')
iter3 = iter('python')
next(iter3)
next(iter3)
for i in iter3:
print(i)
iter4 = iter('python')
list2 = list(iter4)
print(list2)
# print(next(iter4))