一、函数
1、为什么要用函数
a、避免代码重用
b、提高代码的可读性
2、函数的调用
返回值=函数名(参数1,参数2)
函数定义---返回值
关键字:return
3、return的作用:
a、结束函数的执行
b、返回要返回的值
4、返回值的两种情况
a、返回值为None
def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) str_len = mylen() print(str_len)
def ret(): print(111) return print(222) re = ret() print(re)
def ret(): print(111) return None print(222) re = ret() print(re)
b、返回值不为None
1、返回一个值
def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 return length str_len = mylen() print(str_len)
2、返回多个值
5、函数的调用----接受返回值
a、返回值为None 不接受
b、返回值不为None
1、返回一个值
用一个变量接受
2、返回多个值
a、用一个变量接受,接受的结果是一个元祖
b、有多少个返回值就用多少个值接受
6、参数
a、参数----站在定义函数的角度
1、位置参数
2、默认参数
3、动态参数
a、*args
b、**kwargs
顺序:位置参数、*args、默认参数、**kwargs
b、参数----站在调用函数的角度上
1、按照位置传参
2、按照关键字传参
3、动态传参*tup,**dic
7、参数分为形参和实参
a、实参:调用函数的时候传入的参数
8、位置参数
a、位置参数必须传值
def aaa(a,b): print(a,b) aaa(1,2)
9、默认参数
a、默认参数可以不传值
def bbb(x=10): print(x) bbb() #x = 10 bbb(20) #x = 20
10、动态参数
def ccc(*args):#1,2,3,4,5 print(args) ccc(1,2,3,4,5)#按位置传参数 t = (1,2,3,4,5) ccc(t) ((1, 2, 3, 4, 5),) ccc(*t) (1, 2, 3, 4, 5) 复制代码
def ddd(**kwargs): print(kwargs) ddd(k = 'a',j = 'b')#按关键字传参数
def eee(*args,**kwargs): print(args,kwargs) eee(12,123)
11、命名空间
a、命名空间分为三种
1、全局命名空间
2、局部命名空间
3、内置命名空间
b、三种命名空间的顺序:内置命名空间>全局命名空间>局部命名空间
c、取值
1、在局部调用:局部命名空间->全局命名空间->内置命名空间
x = 1 def f(x): print(x) print(10)
2、在全局调用:全局命名空间->内置命名空间
x = 1 def f(x): print(x) f(10) print(x)
12、作用域
a、 作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
b、 全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
c、局部作用域:局部名称空间,只能在局部范围内生效
作用域:
小范围的可以用大范围的
但是大范围的不能用小范围的
范围从大到小(图)
在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
如果都没有,报错
13、闭包
a、闭包分为:
1、闭:内部函数
2、包:包含对外部函数的作用域中变量的引用
b、闭包常用的的形式
def hei(): x = 20 def inner(): print(x) #局部的 return inner i = hei() i() #全局
14、函数值装饰器
a、装饰器的本质:闭包函数
b、装饰器的功能:就是在不改变原函数调用方式的情况下,在这个函数的前后加上扩展功能
def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def func1(a): print(a) func1(1)
15、装饰器的开放封闭原则:
a、对扩展是开放的
b、对修改是封闭的
def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' re = func(*args,**kwargs) '''执行函数之后要做的''' return re return inner
16、装饰器应用场景
a、计算func的执行时间
b、登录认证
17、可迭代
a、字符串,列表,集合,字典,元祖这些度可以for循环,说明他们是可迭代的
b、迭代就是:将某个数据集内的数据一个挨一个的取出来,就 叫做可迭代
c、可迭代对应标志:__iter__
18、迭代协议
a、希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求
b、可迭代协议——凡是可迭代的内部都有一个__iter__方法
19、迭代器协议
a、迭代器协议 : 内部实现了__iter__ __next__方法
可迭代和迭代器的不同点 : 迭代器多实现了一个__next__方法
可迭代和迭代器的相同点 : 都可以用for循环
20、判断迭代器和可迭代的方法
a、第一种:判断内部是不是实现了 __next__
'__next__' in dir(o)
b、第二种
from collections import Iterable #可迭代 from collections import Iterator #迭代器 isinstance(o,Iterable) isinstance(o,Iterator)
21、生成器
a、生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,
挂起函数的状态,以便下次重它离开的地方继续执行
b、生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器函数
def func(): print('aaaa') a = 1 yield a #返回第一个值 print('bbbb') yield 12 #返回第二个值 ret = func() #拿到一个生成器 print(ret) print(next(ret)) #取第一个值 print(next(ret)) #取第二个值 print(next(ret)) #取第三个值 会报错 因为没有第三个值
22、列表推导式
平常:
for i in range(100): print(i*i)
列表推到:
l =[i*i for i in range(100)] print(l)
23、递归函数
a、在一个函数里调用自己
b、Python递归最大层数限制997
c、最大层数限制是python默认的,可以做修改,但是不建议你修改
d、递归实例
def age(n): if n == 1: return 40 else: ret = age(n-1) return ret + 2 age(5)
e、递归结束标志:return
递归三级菜单
menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': {}, } def threeLM(menu): for key in menu: print(key) k = input(">>>") if k in menu: threeLM(menu[k]) threeLM(menu)
24、匿名函数
a、 匿名函数 简单的需要用函数去解决的问题 匿名函数的函数体 只有一行,也叫lambda
b、 函数名 = lambda 参数 :返回值
c、参数可以有多个,用逗号隔开,匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值。返回值和正常的函数一样可以是任意数据类型
add2 = lambda x,y : x+y ret = add2(1,2) print(ret)
l = [1,2,3,4] print(list(map(lambda x:x*x , l)))
25、内置函数
a、isinstance 判断变量的数据类型
temp = "asdfsdfs" r = isinstance(temp, list) print(r)
b、lambda用法:
def f1(): return 123 f2 = lambda :123 r1 = f1() r2 = f2() print(r1,r2)
def f3(a1,a2): return a1 + a2 f4 = lambda a1,a2: a1 + a2 r3 = f3(1,2) r4 = f4(3,4) print(r3,r4)
c、abs--取绝对值
i = abs(-123) print(123)
d、divmod 除商得余数---例如分页
a = 10 / 3 print(a) r = divmod(10,3) print(r) 结果: 3.33333335 (3,1)
e、eval -----强制不转换输入类型的格式
ret = eval("1 + 3") print(ret) 结果:4
f、filter (过滤)
ret = filter(lambda x: x >22, [11,22,33,44]) for i in ret: print(i)
g、map 无论是map还是filter,得到的结果都是可迭代的对象,迭代器的实例
def f1(x): if x % 2 == 1: return x + 100 else: return x ret = map(f1, [1,2,3,4,5]) ret2 = map(lambda x: x + 100if x % 2 == 1 else x ,[1,2,3,4,5]) print(ret) for i in ret : print(i)
h、max()最大数 min() 最小数
li = [11,22,123,1] r = max(li) print(r) a = min(li) print(a)
g、pow(x,y) ----就是求x的y次方
i = pow(2,100) print(i)
k、zip ---意思就是取两个变量中索引相对应的值
li1 = [11,22,33,44] li2 =["a",'VV',"c","E"] r = zip(li1,li2) print(r) for i in r : print(i)
l、、open---打开,关闭,close
模式 描述 r 打开一个文件为只读。文件指针被放置在文件的开头。这是默认模式。 rb 打开一个文件只能以二进制格式读取。文件指针被放置在文件的开头。这是默认模式。 r+ 打开用于读和写文件。文件指针置于该文件的开头。 rb+ 打开用于读取和写入二进制格式的文件。文件指针置于该文件的开头。 w 打开一个文件只写。如果文件存在覆盖该文件。如果该文件不存在,则创建写入新文件。 wb 打开一个文件只能以二进制格式写入。如果文件存在覆盖该文件。如果该文件不存在,则创建写入新文件。 w+ 打开文件为写入和读取模式。如果文件存在覆盖现有文件。如果该文件不存在,创建用于读写操作的新文件。 wb+ 打开用于以二进制格式写入和读出文件。如果文件存在覆盖现有文件。如果该文件不存在,创建用于读写操作的新文件。 a 打开用于追加的文件。文件指针是在文件是否存在该文件的末尾。也就是说,该文件是在追加模式。如果该文件不存在,它会创建一个用于写入的新文件。 ab 打开文件用于二进制格式追加。文件指针是在文件是否存在该文件的末尾。也就是说,文件是在追加模式。 如果该文件不存在,它会创建一个用于写入的新文件。 a+ 打开文件为追加和读取方式。文件指针是在文件是否存在该文件的末尾。该文件以追加模式打开。如果该文件不存在,它将创建用于读写操作的新文件。 ab+ 打开一个文件以附加和二进制格式读取模式。如果该文件存在文件指针在该文件的末尾。该文件以追加模式打开。如果该文件不存在,它将创建读写操作的新文件。