python3函数
2022-02-20 21:57:10 1 举报
AI智能生成
python3函数
作者其他创作
大纲/内容
函数闭包
闭包定义
内层函数对外层函数(非全局)的变量的引用. 叫闭包
闭包作用
闭包的作用就是让⼀个变量能够常驻内存. 供后面的程序使用
def outer():
name = "alex"
# 内部函数
def inner():
print(name) #闭包
return inner
func = outer() #访问外部函数, 获取到内部函数的函数地址
func() #访问内部函数
def outer():
name = "alex"
# 内部函数
def inner():
print(name) #闭包
return inner
func = outer() #访问外部函数, 获取到内部函数的函数地址
func() #访问内部函数
__closure__
func.__closure__检测函数是否是闭包
函数三大器
装饰器
子主题
子主题
子主题
子主题
子主题
迭代器
什么是迭代器
迭代器指的是迭代取值的工具
关键字
__iter__()和__next__()
Iterable
迭代对象:内部包含__iter__()函数
Iterator
迭代器:内部包含__iter__() 同时包含__next__()
可迭代对象
可迭代对象:str, list, tuple, dict, set.
isinstence():用来查看⼀个对象是什么类型
迭代器特点
节省内存
惰性机制
不能反复, 只能向下执⾏
模拟for循环
使⽤while循环+迭代器来模拟for循环(必须要掌握)
list00 = [1, 2, 3]
lst_iter = list00.__iter__()
while True:
try:
i = lst_iter.__next__()
print(i)
except StopIteration:
break
list00 = [1, 2, 3]
lst_iter = list00.__iter__()
while True:
try:
i = lst_iter.__next__()
print(i)
except StopIteration:
break
生成器
什么是生成器
⽣成器实质就是迭代器
关键字
yield
获取⽣成器
通过⽣成器函数获取
__next__()方法
函数有yield. 那么这个函数就是⼀个⽣成器函数,通过__next__()方法执行生成器函数。
调用__next__()方法时,遇到yield,则函数的一段执行结束,返回yield后面表达式。
最后⼀个yield执⾏完毕. 再次调用__next__()方法程序报错:StopIteration。
send()方法
函数有yield. 那么这个函数就是⼀个⽣成器函数,通过send()方法执行生成器函数。
调用send()方法时,先将send()中的参数传递给yield,向下执行遇到yield,则函数的一段执行结束,返回yield后面表达式。
在第⼀次执⾏⽣成器代码的时候不能使⽤send(),需使用__next__()方法。
send()不能给最后⼀个yield传值。
两个方法比较
send()和next()都是让⽣成器向下走⼀次。
第一次执行⽣成器代码的时,可使用__next__()方法,不能使用send()。
send可以给上⼀个yield的位置传递值, 不能给最后⼀个yield发送值。
def eat():
print("我吃什么啊:")
a = yield "馒头"
print("a=", a)
b = yield "⼤饼"
print("b=", b)
gen = eat() #这个时候函数不会执⾏. ⽽是获取到⽣成器
ret1 = gen.__next__()
print(ret1) #我吃什么啊:馒头
ret2 = gen.send("胡辣汤")
print(ret2) #a= 胡辣汤 大饼
ret3 = gen.send("狗粮")
print(ret3) #b= 狗粮 StopIteration
print("我吃什么啊:")
a = yield "馒头"
print("a=", a)
b = yield "⼤饼"
print("b=", b)
gen = eat() #这个时候函数不会执⾏. ⽽是获取到⽣成器
ret1 = gen.__next__()
print(ret1) #我吃什么啊:馒头
ret2 = gen.send("胡辣汤")
print(ret2) #a= 胡辣汤 大饼
ret3 = gen.send("狗粮")
print(ret3) #b= 狗粮 StopIteration
yield
yield是分段来执⾏⼀个函数
return
直接停⽌执⾏函数
通过推导式来实现⽣成器
语法
语法:(结果 for 变量 in 可迭代对象 if 条件 )
gen = ( i for i in range(1,100) if i % 3 == 0 )
for num in gen:
print(num)
for num in gen:
print(num)
⽣成器的惰性机制
# 生成器的惰性机制:深坑 ==> 生成器要值得时候才拿值.
def func():
print(111)
yield 222
g = func() #⽣成器g
g1 = (i for i in g) #⽣成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) #⽣成器g2. 来源g1
print(list(g)) #获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕. # 111 [222]
print(list(g1)) #获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据
print(list(g2)) # 和g1同理
def func():
print(111)
yield 222
g = func() #⽣成器g
g1 = (i for i in g) #⽣成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) #⽣成器g2. 来源g1
print(list(g)) #获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕. # 111 [222]
print(list(g1)) #获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据
print(list(g2)) # 和g1同理
列表推导式
语法:[ 结果 for 变量 in 可迭代对象 if 条件 ]
字典推导式
dic = {'a': 1, 'b': '2'}
new_dic = {dic[key]: key for key in dic}
print(dic)
print(new_dic)
new_dic = {dic[key]: key for key in dic}
print(dic)
print(new_dic)
集合推导式
lst = [1, -1, 8, -8, 12]
# 绝对值去重
s = {abs(i) for i in lst}
print(s)
# 绝对值去重
s = {abs(i) for i in lst}
print(s)
⽣成器推导式和列表推导式区别
1. 列表推导式比较耗内存. ⼀次性加载. ⽣成器表达式⼏乎不占⽤内存. 使⽤的时候才分配和使⽤内存。
2. 得到的值不⼀样. 列表推导式得到的是⼀个列表. ⽣成器表达式获取的是⼀个⽣成器。
通过数据的转换也可以获取⽣成器
内置函数
lamda匿名函数
sorted()
子主题
子主题
子主题
子主题
filter()
map()
递归函数
常见问题
函数定义
函数定义
函数是对代码块和功能的封装和定义。
def 函数名(): 函数体
关键字
def
函数名
函数名的命名规则和使⽤和变量基本⼀样。
参数列表
声明函数时声明的多个参数,默认情况下,参数值和参数名称是按函数声明时的顺序匹配起来的。
函数体
函数体是函数被执⾏之后要执⾏的代码。以冒号起始,并且缩进。第一行语句一般为注释,描述函数功能。
函数调用
使⽤函数名可以调⽤函数, 写法: 函数名(), 这个时候函数的函数体会被执⾏。
返回值
return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return返回 None。
函数参数
关于函数参数
形参
形参:写在函数声明的位置的变量. 形式上的⼀个完整. 表⽰这个函数需要xxx。
实参
实参:在函数调⽤的时候给函数传递的值, 实际执⾏的时候给函数传递的信息. 表⽰给函数xxx。
传参
传参:给函数传递信息的时候将实际参数交给形式参数的过程。
在实参⾓度看
位置参数
位置参数:在传参过程中,系统会默认按照位置把实参赋值到形参,实参中按位置传递的参数就是位置参数。
关键字参数
关键字参数:实参中以 param = value 的方式传递的参数
优点1:清晰地指出了参数值,提高程序的可读性
优点2:关键字参数不用考虑顺序,对于包含大量参数的函数很有帮助
混合参数
混合参数:实参中位置参数和关键字参数混合的参数
注意:位置参数必须在关键字参数前⾯
def yue(chat, address, age):
yue(age="18", "微信", address="广州") # 错误, 最开始使用了关键字参数, 那么后面的微信的位置就串了, 容易出现混乱
SyntaxError: positional argument follows keyword argument
在形参⾓度看
位置参数
位置参数:声明函数时按位置声明的参数。(在传参过程中,系统会默认按照位置把实参赋值到形参)
默认值参数
默认值参数:函数在声明的时候, 已给出函数参数默认值的参数。
默认值参数,在调⽤的时候可以给出具体的值, 也可以不给值, 使⽤默认值。
当声明多个参数时,必须先声明位置参数, 才能声明默认值参数。
def stu_info(chat, address, sex='男', name, age): # non-default argument follows default argument
stu_info("微信", "北京", '女', "李思思", 20)
动态传参
动态接收位置参数
形参中用*args来表示动态接收位置参数
位置参数 > 默认值参数 > *args :默认值不生效,默认值参数只有当实参等于默认值的时候默认值参数才生效,发挥不了默认效果。
位置参数 > *args > 默认值参数:默认值生效,想要改默认参数值就通过关键字传参,不想改就用默认值。
def chi(a, b, *food, c="娃哈哈"):
chi("⾹蕉", "菠萝", "葫芦娃", "⼝罩") # ⾹蕉 菠萝 ('葫芦娃', '⼝罩') 娃哈哈
当声明多个参数时,必须要有:位置参数 > *args > 默认值参数
动态接收关键字参数
形参中用**kwargs来表示动态接收关键字参数
位置参数 > *args > 默认值参数 > **kwargs:最终顺序
def chi(a, b, *args, c='馒头', d='黄焖鸡', **kwargs):
chi("⾹蕉", "菠萝", "葫芦娃", "⼝罩", "红烧肉", d="⼤⽶饭", e="⼩⽶饭", f="⻩⽠", g="茄⼦", h='可乐')
#⾹蕉 菠萝 ('葫芦娃', '⼝罩', '红烧肉') 馒头 ⼤⽶饭 {'e': '⼩⽶饭', 'f': '⻩⽠', 'g': '茄⼦', 'h': '可乐'}
当声明多个参数时,必须要有:位置参数 > *args > 默认值参数 > **kwargs
动态参数的另⼀种传参方式
func(*list)或func(*str):把列表或字符串等可迭代对象按顺序打散传参。
def fun(*args):
print(args)
lst = [1, 4, 7]
fun(*lst) # 可以使⽤*把⼀个列表按顺序打散
print(args)
lst = [1, 4, 7]
fun(*lst) # 可以使⽤*把⼀个列表按顺序打散
func(**dict):把字典按顺序打散传参。
def fun(**kwargs):
print(kwargs)
dic = {'a':1, 'b':2}
fun(**dic)
print(kwargs)
dic = {'a':1, 'b':2}
fun(**dic)
函数调用
命名空间
命名空间分类
全局命名空间
直接在py⽂件中, 函数外声明的变量都属于全局命名空间
局部命名空间
在函数中声明的变量会放在局部命名空间
内置命名空间
存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
命名空间加载顺序
内置命名空间 >> 全局命名空间 >>局部命名空间(函数被执⾏的时候)
命名空间取值顺序
局部命名空间 >> 全局命名空间 >> 内置命名空间
作用域
全局作⽤域
全局命名空间 + 内置命名空间
局部作⽤域
局部命名空间
globals()和locals()
globals()函数来查看全局作⽤域中的内容
locals()函数来查看局部作⽤域中的变量和函数信息
函数的嵌套
嵌套函数的调用
遇到了()就是函数的调⽤,如果没有()就不是函数的调⽤
函数的执⾏顺序
依次往下执行,遇到函数调用,执行调用函数
关键字global和nonlocal
global
global:表示不再使⽤局部作⽤域中的内容了. ⽽改⽤全局作⽤域中的变量
nonlocal
nonlocal: 表⽰在局部作⽤域中, 调⽤⽗级命名空间中的变量.
函数的返回
关键字
return
返回值
return [表达式]
如果 return 什么都不写或者⼲脆不写return ,那么返回的就是None。
如果 return 后⾯写了⼀个值,则调⽤者可以接收⼀个结果。
如果 return 后⾯写了多个结果,,则调⽤者可以接收⼀个tuple,调⽤者可以直接解构成多个变量。
return作用
遇到return,此函数结束, 函数后⾯的东⻄将不会再执⾏。
函数名使用
函数名的内存地址
# 1. 函数名的内存地址
def func():
print("呵呵")
print(func) #<function func at 0x00000000004D1EA0>
def func():
print("呵呵")
print(func) #<function func at 0x00000000004D1EA0>
赋值给其他变量
# 2. 函数名可以赋值给其他变量
def func():
print("呵呵")
a = func # 把函数名当成⼀个变量赋值给另⼀个变量
a() #呵呵 (函数调用 func())
def func():
print("呵呵")
a = func # 把函数名当成⼀个变量赋值给另⼀个变量
a() #呵呵 (函数调用 func())
当做容器类的元素
# 3. 函数名可以类的当做容器元素
def func1():
print("呵呵")
def func2():
print("呵呵")
def func3():
print("呵呵")
def func4():
print("呵呵")
lst = [func1, func2, func3, func4]
for i in lst:
i()
#呵呵 呵呵 呵呵 呵呵
def func1():
print("呵呵")
def func2():
print("呵呵")
def func3():
print("呵呵")
def func4():
print("呵呵")
lst = [func1, func2, func3, func4]
for i in lst:
i()
#呵呵 呵呵 呵呵 呵呵
当做函数的参数
# 4. 函数名可以当做函数的参数
def func11():
print("吃了么")
def func22(func):
print("我是func22")
func() # 执⾏传递过来的 func
print("我是func22")
func22(func11) # 把函数 func11当成参数传递给 func22 的参数 func
#我是func22 吃了么 我是func22
def func11():
print("吃了么")
def func22(func):
print("我是func22")
func() # 执⾏传递过来的 func
print("我是func22")
func22(func11) # 把函数 func11当成参数传递给 func22 的参数 func
#我是func22 吃了么 我是func22
当做函数的返回值
# 5. 函数名可以作为函数的返回值
def func_1():
print("这⾥是函数 1")
def func_2():
print("这⾥是函数 2")
print("这⾥是函数 1")
return func_2
fn = func_1() # 执⾏函数1. 函数1返回的是函数2, 这时fn指向的就是上⾯函数2
fn() # 这⾥是函数 1 这⾥是函数 1 这⾥是函数 2
def func_1():
print("这⾥是函数 1")
def func_2():
print("这⾥是函数 2")
print("这⾥是函数 1")
return func_2
fn = func_1() # 执⾏函数1. 函数1返回的是函数2, 这时fn指向的就是上⾯函数2
fn() # 这⾥是函数 1 这⾥是函数 1 这⾥是函数 2
0 条评论
下一页