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