1.函数基本知识点回顾
知识点:
函数定义格式: def 函数名(): 函数体
函数的注意事项:
1:先定义再调用,
2:不调用不执行,
3:每调用一次执行一次
4:如果函数没有返回值,默认返回的是None
示例:
# 函数特点: 必须先定义再调用 如果函数没有返回值,默认返回的是None
# 定义一个函数 : def 函数名(): 函数体
def func1():
print('我是func1函数')
# 省略了return None
# 调用函数 : 函数名()
print(func1()) # 先调用func1(),然后打印func1的返回值
print('-------------------------------')
# 定义一个函数 : def 函数名(): 函数体
def func2():
print('我是func2函数')
return 2
# 调用函数 : 函数名()
print(func2()) # 先调用func2(),然后打印func2的返回值
2.函数名记录的是函数引用地址
知识点:
函数名: 记录的是当前对应函数的引用地址
函数名(): 调用函数,执行对应地址里函数内容
示例:
# 定义函数
def func1():
print('我是func1函数')
return 1
# 调用函数
print(func1()) # 结果? 先调用func1(),再打印func1()的返回值
print('---------------------------------------------')
# 基础班的时候错误写法?原来你们认为这是错误的,其实这是打印了func1函数的地址
# 因为函数名其实记录的就是函数的地址,所以打印函数名,结果出现地址
print(func1) # 结果? 地址<function func1 at 0x0000013C23EF5310>
# 通过以上结果说明: 所有的函数名本质记录的就是当前函数的地址
3.函数作为参数传递
知识点:
定义带参函数: def 函数名(形参): 函数体
调用带参函数: 函数名(实参)
函数名作为实参传递: 本质传递的是对应函数的引用地址
示例:
# 定义函数1
def func1():
print('我是func1函数...')
# 1.测试
print(func1) # func1记录的是func1函数的地址 <function func1 at 0x0000019D730A5310>
func1()
print('---------------------------------')
# 2.演示函数名作为参数传递
# 定义函数2
def func2(show): # 形参show=func1=0x0000019D730A5310
print(show) # show此时记录的是传进来的func1的地址:<function func1 at 0x0000022D7E6F5310>
show() # show()=func1() 本质就是调用了func1函数:控制台结果是我是func1函数...
# 调用func2函数,把函数func1引用地址传递给show变量 # show=func1=0x0000019D730A5310
func2(func1) # 实参func1
4.闭包作用
知识点:
闭包作用: 能够保存外部函数变量值(让外部函数变量一直不销毁),重复使用
示例:
# 定义函数
def outer():
a = 10 # 函数运行完就销毁了
return a
# 调用函数
b = outer() # 新的变量b接收的: b =10
print(b + 1)
print(b + 2)
print(b + 3)
print(b + 4)
print(b + 5)
# 需求:使用a变量 依次 +1=11 +2=12 +3=13 +4=14 +5=15
# 闭包作用:闭包可以解决以上问题,闭包可以不让a变量销毁,重复使用a
5.闭包使用
知识点:
闭包三个条件:
1:有嵌套(外部函数里嵌套内部函数)
2:有引用(内部函数使用了外部函数的变量或者形参)
3:有返回(外部函数把内部函数名返回,本质返回的是内部函数的地址)
示例:
"""
闭包条件:
1.有嵌套(外部函数套一个内部函数)
2.有引用(内部函数引用外部函数的变量或者形参)
3.有返回(外部函数把内部函数名返回) 本质返回的是地址
"""
# 定义闭包
def outer(a): # 外部函数
# a = 10
def inner(b): # 内部函数 有嵌套
print(a + b) # 有引用 # 由于内部函数在重复使用外部函数的a变量,所以外部函数的a变量一直没有销毁
return inner # 有返回,注意:此处一定不要多了括号!!!
# 需求依次a变量 +1=11 +2=12 +3=13 +4=14 +5=15
# 调用外部函数获取内部函数地址
# add = inner = 内部函数的地址
add = outer(10) # 打开外面的盒子获取里面的盒子 外部函数的变量值只传1次即可
# 调用内部函数 内部函数就可以一直使用外部函数的变量
add(1) # add(1) 本质根据内部函数的地址去调用内部函数把1传给b
add(2) # add(2) 本质根据内部函数的地址去调用内部函数把2传给b
add(3) # add(3) 本质根据内部函数的地址去调用内部函数把3传给b
add(4) # add(4) 本质根据内部函数的地址去调用内部函数把4传给b
add(5) # add(5) 本质根据内部函数的地址去调用内部函数把5传给b
6.拓展nonlocal关键字
知识点:
nonlocal: 能够让内部函数去修改外部函数的变量
global: 声明全局变量
示例:
# 需求:闭包内部函数修改外部函数的变量值
"""
闭包条件:有嵌套 有引用 有返回
"""
# 定义外部函数
def outer():
a = 100
# 定义内部函数
# 拓展: 内部函数想修改外部函数的变量用nonlocal
def inner():
nonlocal a
a += 1
print(f'内部函数修改完外部函数a值后:{a}') # 修改后
print(f'外部函数a值:{a}') # 优先于内部函数执行了,打印的初始值100
return inner
# 使用闭包
f = outer() # 先调用外部函数,再接收内部函数地址
f() # 调用内部函数
7.装饰器入门
知识点:
装饰器作用: 不改变原有函数(不改变源码和不改变调用方式)的基础上,去增加额外功能
装饰器本质: 就是一个闭包函数
装饰器条件:
1:有嵌套(外部函数里嵌套内部函数)
2:有引用(内部函数使用了外部函数的变量或者形参)
3:有返回(外部函数把内部函数名返回,本质返回的是内部函数的地址)
4:有额外功能(给需要装饰的原有函数增加了额外功能)
装饰器使用:
方式1: 传统方式: 装饰完的函数 = 装饰器名(原有函数)
方式2: 语法糖方式: @装饰器名
示例:
"""
装饰器功能: 不改变原有函数(不改变源码,不改变调用方式)的基础上,去增加额外功能
装饰器条件
1.有嵌套 2.有引用 3.有返回 4.有额外功能
"""
# 需求: 已知一个函数comment,只有发表评论功能,需要写一个装饰器去装饰下comment函数
# 增加一个额外的功能:在发表评论前先提示登录
# 3.定义一个装饰器(形参是原有函数)
def outer(fun): # fun = comment
def inner(): # 有嵌套
print('请先登录') # 有额外功能
fun() # 有引用,调用传进来的原有函数 fun() == comment()
return inner # 有返回
# 1.定义原有函数
# 4.2 使用装饰器语法糖方式(不好理解但使用简单点): @装饰器名
@outer
def comment():
print('发表评论')
# 4.1使用装饰器传统方式(好理解但使用麻烦点): 装饰完的原有函数 = 装饰器名(原有函数名)
comment = outer(comment) # 传进去原有函数,出来的是装饰完的原有函数
# 2.调用原有函数
comment() # 使用了装饰器后,调用的其实是装饰完的内部函数
8.回顾函数分类和不定长参数
知识点:
回顾函数分类:
无参无返回值的函数
定义: def 函数名(): ...
调用: 函数名()
无参有返回值的函数
定义: def 函数名(): ... return 返回值
调用: 用变量接收返回值 = 函数名()
有参无返回值的函数
定义: def 函数名(形参): ...
调用: 函数名(实参)
有参有返回值的函数
定义: def 函数名(形参): ... return 返回值
调用: 用变量接收返回值 = 函数名(实参)
回顾不定长参数:
*args: 底层是元组形式
**kwargs: 底层是字典形式
9.装饰器装饰无参无返回值的函数
示例:
"""
无参无返回值的函数
定义: def 函数名(): ...
调用: 函数名()
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner():
print('正在努力计算中...')
func() # 调用传进来的原有函数
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum():
a = 10
b = 20
sum = a + b
print(sum)
# 2.调用原有函数
get_sum()
10.装饰器装饰有参无返回值的函数
示例:
"""
有参无返回值的函数
定义: def 函数名(形参): ...
调用: 函数名(实参)
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner(a,b):
print('正在努力计算中...')
func(a,b) # 调用传进来的原有函数 get_sum(a,b)
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum(a,b):
sum = a + b
print(sum)
# 2.调用原有函数
# 如果使用了装饰器,再调用的时候其实本质调用的是装饰器里内部函数
get_sum(10,20)
11.装饰器装饰无参有返回值的函数
示例:
"""
无参有返回值的函数
定义: def 函数名(): ... return 返回值
调用: 用变量接收返回值 = 函数名()
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner():
print('正在努力计算中...')
sum = func() # 调用传进来的原有函数 get_sum()
return sum
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum():
a = 10
b = 20
sum = a + b
return sum
# 2.调用原有函数(不能改变原有调用方式的)
sum = get_sum() # 调用的是装饰完的内部函数 inner()
print(sum)
12.装饰器装饰有参有返回值的函数
示例:
"""
有参有返回值的函数
定义: def 函数名(形参): ... return 返回值
调用: 用变量接收返回值 = 函数名(实参)
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner(a,b):
print('正在努力计算中...')
sum = func(a,b) # 调用传进来的原有函数 get_sum(a,b)
return sum
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum(a,b):
sum = a + b
return sum
# 2.调用原有函数(不能改变原有调用方式的)
sum = get_sum(10,20) # 调用的是装饰完的内部函数 inner(10,20)
print(sum)
sum = get_sum(30,40) # 调用的是装饰完的内部函数 inner(30,40)
print(sum)
13.装饰器装饰有可变参数无返回值的函数
示例:
"""
有参无返回值的函数
定义: def 函数名(形参): ...
调用: 函数名(实参)
*args: 元组
**kwargs: 字典
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
print('正在努力计算中...')
func(*args, **kwargs) # 调用传进来的原有函数 get_sum(*args, **kwargs)
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
sum = 0
# 遍历元组求和
for i in args:
sum += i
# 遍历字典求和
for i in kwargs.values():
sum += i
print(sum)
# 2.调用原有函数
# 如果使用了装饰器,再调用的时候其实本质调用的是装饰器里内部函数
get_sum(10, 20, a=30, b=40) # 调用的内部函数 inner(*args, **kwargs)
14.通用装饰器
示例:
"""
有参有返回值的函数
定义: def 函数名(形参): ...return 返回值
调用: 变量接收返回值 = 函数名(实参)
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
print('正在努力计算中...')
sum = func(*args, **kwargs) # 调用传进来的原有函数 get_sum(*args, **kwargs)
return sum
return inner
# 1.定义原有函数
@outer # 4.语法糖方式
def get_sum(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
sum = 0
# 遍历元组求和
for i in args:
sum += i
# 遍历字典求和
for i in kwargs.values():
sum += i
return sum
# 2.调用原有函数
# 如果使用了装饰器,再调用的时候其实本质调用的是装饰器里内部函数
sum = get_sum(10, 20, a=30, b=40) # 调用的内部函数 inner(*args, **kwargs)
print(sum)
15.带参数的装饰器(了解)
示例:
"""
有参数的装饰器:
有嵌套+1
有引用
有返回+1
有额外功能+1
"""
# 需求: 在原有函数计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...
# 5.编写带有参数的装饰器
def logging(flag):
# 3.编写装饰器(有嵌套,有引用,有返回,有额外功能)
def outer(func):
def inner(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
if flag == '+':
print('正在努力做加法计算中...')
elif flag =='-':
print('正在努力做减法运算中...')
sum = func(*args, **kwargs) # 调用传进来的原有函数 get_sum(*args, **kwargs)
return sum
return inner
return outer
# 1.定义原有函数
@logging("+") # 4.语法糖方式 6.修改成最外层装饰器
def get_sum(*args, **kwargs): # args = (10,20) kwargs={'a': 30, 'b': 40}
sum = 0
# 遍历元组求和
for i in args:
sum += i
# 遍历字典求和
for i in kwargs.values():
sum += i
return sum
# 2.调用原有函数
# 如果使用了装饰器,再调用的时候其实本质调用的是装饰器里内部函数
sum = get_sum(10, 20, a=30, b=40) # 调用的内部函数 inner(*args, **kwargs)
print(sum)
# 7.测试减法
@logging('-')
def sub(a,b):
cha = a-b
return cha
cha = sub(20,10)
print(cha)