day 11 note 高阶函数

day 11 note 高阶函数

01. 高阶函数

1. 函数就是变量

python中定义函数就是定义类型是 function 的变量,函数名就是变量名

变量能做的事情,函数都能做


a = 10
d = 'abc'
e = [10, 20, 30]
b = lambda x: x*2

def b(x):

return x*2

c = {'a': 10, 'b': 100}
print(type(a), type(b), type(c))

x = 100
def func1():
    print('我是一个函数')
    

1)一个变量可以给另外一个变量赋值


y = x
print(y+100)

z = func1
z()

2) 修改变量的值


x = 'abc'

print(x+'123', x.replace('a', '100'))

func1 = 100

func1()     # TypeError: 'int' object is not callable

print(func1, func1+200)

3)变量作为序列的元素


list1 = [x, 200]
print(list1)    # [100, 200]
print(list1[0] - 100)

list2 = [func1, 200, func1()]
print(list2)     # [<function func1 at 0x10a776710>, 200, None]
list2[0]()    # func1()

4)变量作为函数的参数


def func2(m):
    print(f'x:{m}')

a = 100
func2(a)

func2(func1)

5)变量作为函数的返回值


def func3():

s = 100

    def s():
        print('我是小函数')
    return s

print(func3()-50)

func3()()   # s()

面试题

list3 = []
for i in range(5):
    list3.append(lambda x:x*i)

"""
i = 0:  [lambda x:x*i]
i = 1: [lambda x:x*i, lambda x:x*i]
i = 2: [lambda x:x*i, lambda x:x*i, lambda x:x*i]
i = 3: [lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i]
i = 4: [lambda x:x*i, lambda x:x*i, lambda x:x*i, lambda x:x*i, lambda x:x*i]
list3 = [lambda x:x*i, lambda x:x*i, lambda x:x*i, lambda x:x*i, lambda x:x*i]

lambda x:x*i
"""
print(list3[1](2))    # 8
print(list3[2](2))    # 8


02. 实参高阶函数

1. 实参高阶函数

参数是函数的 函数就是 实参高阶函数

func1就是实参高阶函数


def func1(x):
    print(x())

def func2(m=10):
    print('你好!')

func1(func2)

2. 系统常见实参高阶函数的使用

max、min、sorted、map、reduce

1. max、min、

1)max(序列) - 比较序列中元素的大小来获取值最大的元素

2)max(序列, key=函数) - 函数决定求最大值的时候的比较对象

参数key的要求:

a.是一个函数

b.这个函数有且只有一个参数(这个参数指向的就是序列中的元素)

c.函数要有一个返回值(比较对象)

nums = [23, 78, 90, 78, 233, 91]
print(max(nums))   # 233

求列表中个位数最大的元素

nums = [19, 78, 76, 55, 30, 12]

def f1(item):

return item % 10

result = max(nums, key=f1)

result = max(nums, key=lambda item: item % 10)
print(result)


students = [
    {'name': '小明', 'age': 23, 'score': 90},
    {'name': '张三', 'age': 30, 'score': 78},
    {'name': '小红', 'age': 18, 'score': 82},
    {'name': 'Tom', 'age': 26, 'score': 99}
]

求所有学生中成绩最高的学生

def f2(item):

print(f'item:{item}')

return item['score']

print(max(students, key=lambda item: item['score']))

print(max(students, key=f2))

求年龄最小的学生

print(min(students, key=lambda item: item['age']))

练习:获取列表中数字各位数的和最大的元素

nums = [23, 78, 90, 73, 233, 91]

515910810   -> 78

nums = [23, 78, 90, 73, 233, 91]


def f3(item):
    n = [int(x) for x in str(item)]
    return sum(n)


print(max(nums, key=f3))

2. sorted

sorted(序列) - 比较序列中元素的大小对序列中的元素从小到大排序

sorted(序列, key=函数) - 函数决定排序的时候比较大小的比较对象

函数要求:

a.是一个函数

b.需要一个参数(指向序列中的元素)

c.需要一个返回值(比较对象)

nums = [19, 78, 76, 55, 30, 12]
result = sorted(nums)
print(result)

练习1:让列表中的元素按照个位数的大小从小到大排序

nums = [19, 78, 76, 55, 30, 12]  ->  [30, 12, 55, 76, 78, 19]

nums = [19, 78, 76, 55, 30, 12]
result = sorted(nums, key=lambda item:item%10)
print(result)    # [30, 12, 55, 76, 78, 19]

练习2:将students按照学生的年龄从大到小排序

students = [
    {'name': '小明', 'age': 23, 'score': 90},
    {'name': '张三', 'age': 30, 'score': 78},
    {'name': '小红', 'age': 18, 'score': 82},
    {'name': 'Tom', 'age': 26, 'score': 99}
]

result = sorted(students, key=lambda item: item['age'])
print(result)

3. map

用法一: 原序列 -> 新序列
map(函数, 序列) - 将序列按照指定的方式进行转换, 返回值是一个map对象(map对象是序列)
a. 是一个函数函数:

b. 有一个参数 (指向原序列中的元素)

c. 需要一个返回值 (新序列中的元素)

用法二:
map(函数, 序列1, 序列2) - 根据序列1和序列2创建一个新的序列
a. 是一个函数:

b. 有两个参数,分别指向两个序列中元素

c. 需要一个返回值(新序列中的元素)

用法一

nums = [19, 78, 76, 55, 30, 12]
result = map(lambda item: item%10, nums)
print(list(result))

result = map(lambda item: item*2, nums)
print(list(result))

用法二

names = ['张三', '李四', '小明', '小花']
ages = [19, 29, 30, 17]

[{'name': '张三', 'age': 19}, {'name':'李四', 'age': 29},...]

result = map(lambda item1, item2: {'name':item1, 'age': item2}, names, ages)
print(list(result))

练习:获取班级所有学生的总成绩

c = [90, 89, 88, 99, 27, 76, 56]
e = [98, 78, 66, 82, 90, 12, 78]
m = [23, 98, 100, 72, 69, 27, 96]
result = map(lambda i1, i2, i3: i1+i2+i3, c, e, m)
print(list(result))


4. reduce

from functools import reduce

reduce(函数, 序列, 初始值)
函数的要求:a. 需要两个参数:
第一个参数 - 第一次指向初始值; 从第二次开始指向上一次的运算结果
第二个参数 - 指向序列中的每个元素
b. 需要一个返回值(决定运算规则)



# (1) 累积求和

nums = [10, 89, 78, 20]

result = reduce(lambda s, item: s+item, nums, 0)

def f1(s, item):
    print(f's:{s}, item:{item}')
    return s+item
result = reduce(f1, nums, 0)
print(result)    # 197

f1(0, 10)  -> 10

f1(10, 89)  -> 10+89->99

f1(99, 78)  -> 99+78 -> 177

f1(177, 20)  -> 177+20 -> 197

# (2) 累积求乘积

nums = [8, 9, 5, 2]
result = reduce(lambda s, item: s*item, nums, 1)
print(result)

# 练习:将数字序列中的元素全部拼接在一起

[10, 89, 78, 20] -> 10897820

nums = [10, 89, 78, 20]
result = reduce(lambda s, item: s+str(item), nums, '')
print(result)

f('', 10)  -> ''+str(10) -> '10'

f('10', 89) -> '10'+str(89) -> '1089'

nums = ['10', '89', '78', '20']




03. 无参装饰器

1.什么是装饰器

作用:装饰器是用来给函数添加功能
本质:就是一个函数(实参高阶函数+返回值高阶函数+糖语法)
用法(套路):
def 函数名1(参数1):
def 函数名2():
新增功能的代码
调用原函数的代码: 参数1()
return 函数名2

说明:
1) 函数名1 - 装饰器的名称,根据新增的功能来命名
2) 参数1 - 需要添加功能的函数(原函数), 一般命名成f、fn
3) 函数名2 - 添加完功能的新函数的函数名, new_f、new_fn

@@@装饰器用法@@@

用法(套路):
def 函数名1(参数1):
**def 函数名2(*args, **kwarg):
新增功能的代码
*原函数的返回值 = 调用原函数的代码: 参数1(args, kwarg)
return 原函数的返回值
return 函数名2

说明:
1) 函数名1 - 装饰器的名称,根据新增的功能来命名
2) 参数1 - 需要添加功能的函数(原函数), 一般命名成f、fn
3) 函数名2 - 添加完功能的新函数的函数名, new_f、new_fn


# 给函数添加统计函数执行时间的功能

# 方法一:给需要添加功能的函数添加新增功能的代码

# 存在的问题:如果给不同的函数添加相同的功能,相同的功能的代码要写多遍

def fun1():
    start = time.time()
    print('函数1的功能')
    end = time.time()
    print(f'执行时间:{end-start}')

def func2(x, y):
    start = time.time()
    print(x+y)
    end = time.time()
    print(f'执行时间:{end - start}')


fun1()
func2(10, 20)

# 方法二:将需要添加的功能封装到一个函数中

# 存在问题:原函数并没有新增功能

def func3():
    print('hello world!')

def func4():
    print('你好世界!')

def count_time(f):
    # 获取开始时间
    start = time.time()
    # 调用原函数
    # func3()
    f()
    # 获取结束时间
    end = time.time()
    # 计算时间差
    print(f'执行时间:{end-start}')

count_time(func3)
count_time(func4)
func3()

# 方法三: 装饰器

"""
用法(套路):

def 函数名1(参数1):
    def 函数名2(*args, **kwarg):
        新增功能的代码
        原函数的返回值 = 调用原函数的代码: 参数1(*args, **kwarg)
        return 原函数的返回值
    return 函数名2

说明:
1) 函数名1  - 装饰器的名称,根据新增的功能来命名
2) 参数1  - 需要添加功能的函数(原函数), 一般命名成f、fn
3) 函数名2  -  添加完功能的新函数的函数名, new_f、new_fn
"""
def count_time(f):
    def new_f(*args, **kwargs):
        start = time.time()
        result = f(*args, **kwargs)
        end = time.time()
        print(f'执行时间:{end-start}')
        return  result
    return new_f

print('==================================')
@count_time
def func5():
    print('你好, Python')


@count_time
def func6():
    print('*****')

@count_time
def func7(num1, num2):
    print(num1 + num2)

@count_time
def func8(num):
    return num**2


func5()

print('==================================')
func6()

print('==================================')
func7(10, 20)

print('==================================')
result = func8(9)
print(result)

print('===========================================')

练习:写一个装饰器,在函数开始执行的时候打开 'start!'

def start(f):
    def new_f(*args, **kwargs):
        print('start!')
        re = f(*args, **kwargs)
        return re
    return new_f

@start
def func11():
    print('hello world!')

@start
def func22(a, b):
    return a*b

func11()
func22(10, 29)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值