第五章 函数
5.1三元运算/三目运算
v = 前面 if 条件语句 else 后面
#如果条件成立,"前面"赋值给v,否则后面赋值给v.
v = a if a>b else b # 取a和b中值较大的赋值给v
# 让用户输入值,如果值是整数,则转换成整数,否则赋值为None
data = input('请输入值:')
value = int(data) if data.isdecimal() else None
5.2 函数
5.2.1.函数介绍
-
截止目前为止,都是面向过程式编程.可读性差,重复性高,容易出错.
-
对于函数编程:
- 本质:将N行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码并执行。
- 场景:
- 代码重复执行。
- 代码量特别多超过一屏,可以选择通过函数进行代码的分割。
-
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率.
py3中给我们提供了许多内建函数,如len()/print()等等,我们也可以自定义函数,这叫做用户自定义函数 .
5.2.2.函数定义和表达
-
定义如下:
-
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
-
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
-
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
-
函数内容以冒号起始,并且缩进。
-
return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
注意: 遇到return语句,后面的代码不执行.
-
-
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名称(形参): #算列表中所有元素的和,括号中可以添加形式参数.简称形参,也可以不加. 函数代码
-
最简单的形式
def hello() : print("Hello World!") #定义函数 hello() # 调用函数,输出"Hello World!"
-
复杂一些,加上参数
# 计算列表中的元素的和 def sum_list_element(list1): sum = 0 for i in list1: sum += 1 print(sum) # 调用函数 sum_list_element([1,2,3,4,5,6,7,8,9]) # 输出45
-
加上return的应用(重点) --> 返回多个值自动装换为元组
# 比较2个数的大小,并返回得到较大的数 def compare_num(a,b): v = a if a > b else b return v # 如果没有return语句, print(compare_num(5,10)) 输出的是None print(compare_num(5,10)) # 调用函数,得到a,b中较大的数,并打印出来. #函数没有返回值时,默认返回None #函数有返回值时,语句为:return 返回值.返回值可以是任意东西. def compare_num(a,b): return a if a>b else b #和三目运算一起,返回a和b中较大的数. ############################################# # 函数执行到return 语句,就返回,后面的语句不执行. # 若返回值为多个,默认将其添加到元组中,返回一个元组. def func(a,b,c,d) return a,b,c,d v = func(1,'韩梅梅',[11,22,33,44,55],{'k1':'v1'}) print(v) # (1,'韩梅梅',[11,22,33,44,55],{'k1':'v1'}) 元组,
-
5.2.3函数参数解析
-
参数
def func(a1,a2): 函数体(可调用a1和a2) return 返回值 # 严格按照顺序传参数:位置方式传参。 # 实际参数可以是任意类型。 def check_age(age): #只有1个参数:age,参数数量可以是无穷多个. if age >= 18: print('你是成年人') else: print('你是未成年人') check_age(18) #调用函数,输出你是成年人.
-
位置参数
def func(a1,a2,a3,a4) print(a1,a2,a3,a4) func(1,2,3,4) # 严格按顺序输入参数,顺序是固定的.
-
关键字传参
def func(a1,a2) print(a1,a2) func(a1 = 1 ,a2 = 2) func(a2 = 2,a1 = 1) # 俩者完全一样,全是关键字可以打乱顺序.
-
位置参数和关键字传参混用
###### 这时必须位置参数在前,关键字参数在后 def func(a1,a2,a3,a4) print(a1,a2,a3,a4) func(1,10,a3 = 15,a4 = 88) func(1, 10, a4=15, a3=88) # 俩者等价,正确. func(a1=1,a2=2,a3=3,a4=4) #正确 func(a1=1,a2=2,15,a4 = 88) # 错误 func(1,2,a3 = 15,88) #错误 ################################# # 必须位置参数在前,关键字参数在后, 位置参数 > 关键字参数 #
-
默认参数
def func(a1,a2,a3=9,a4=10): # 默认a3=9,a4=10,这时可以不输入a3 和 a4 参数.默认值为 9 和 10 print(a1,a2,a3,a4) func(11,22) #正确 func(11,22,10) # 正确,修改默认参数a3 = 10 ,参数a4不输入.默认为10 . func(11,22,10,100) #正确 func(11,22,10,a4=100) #正确 func(11,22,a3=10,a4=100) #正确 func(11,a2=22,a3=10,a4=100) #正确 func(a1=11,a2=22,a3=10,a4=100) #正确
-
万能参数(重点)
-
args(打散)可以接受任意个数的位置参数,并将参数转换成元组。
-
没有调用函数 * 字符
def func(*args): print(args) func(1,2,3,True,[11,22,33,44]) # 输出为(1,2,3,True,[11,22,33,44]) 元组 func(*(1,2,3,4,5)) # 如果不加*号,函数会将序列当成一个元素加入到元组中,*相当于拆包.
-
有调用函数 * 字符
def func(*args): print(args) func(*(1,2,3,True,[11,22,33,44])) # 输出为(1,2,3,True,[11,22,33,44]) 元组
-
-
*args 只能用位置传参
def func4(*args): print(args) func4(1) 元组(1,) func4(1,2) 元组(1,2) func4(1,2) func4(1,2)
-
**kwags(打散) 可以接受任意个数的关键字参数,并将参数转换成字典。
-
没有调用函数 ** 字符
def func(**kwargs): print(kwargs) func(k1=1,k2="alex")
-
有调用函数 ** 字符
def func(**kwargs): print(kwargs) func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'}func(*(1,2,3,4,5)) # 如果不加**号,函数会将序列当成一个元素加入到元组中,相当于只有键没没有值,就会报错.
-
**kwags(打散)只能用关键字传参
-
-
5.2.4函数参数默认值使用可变类型--->有坑(重点)
- 补充:对于函数的默认值慎用可变类型。
# 如果要想给value设置默认是空列表
# 不推荐(坑)
def func(data,value=[]):
pass
# 推荐
def func(data,value=None):
if not value:
value = []
def func(data,value=[]):
value.append(data)
return value
v1 = func(1) # [1,]
v2 = func(1,[11,22,33]) # [11,22,33,1]
-
原因
def func(data,value=[]): value.append(data) return value v1 = func(1) # [1,] # 调用函数,作用域得到value=[],添加value=[1,] v2 = func(2) # [1,2,] #调用函数,value=[1,]再次添加元素2, v2 = func(1,[11,22,33]) # [11,22,33,1] ############## def func(a,b=[]) 有什么陷阱? ####### 答: Python函数在定义的时候。默认参数b的值就被计算出来了,即[],因为默认参数b也是一个变量,它指向对象即[],每次调用这个函数,如果改变b的内容每次调用时候默认参数也就改变了,不在是定义时候的[]了.应该换成None .
5.2.5函数参数混用
def func(*args,**kwargs):
print(args,kwargs)
# func(1,2,3,4,5,k1=2,k5=9,k19=999)
func(*[1,2,3],k1=2,k5=9,k19=999)
func(*[1,2,3],**{'k1':1,'k2':3})
func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3})
5.2.6函数作用域
-
函数的作业域
-
作用于全局,对任意一个py文件来说,全局作用域
-
对函数来说:局部作用域
# 在函数中定义的值,只在局部作用域中 # 在全局作用域中找不到# a = 1 b = 2 def func(): a = 10 b = 20 print(a) print(b) func() # 输出10 ,20 print(a) print(b) #输出 1 , 2
-
-
作用域查找数据规则::优先在自己的作用域找数据,自己没有就去 "父级" -> "父级" -> 直到全局,全部么有就报错。
a = b = 1 def func(): b = 5 print(a,b) func() # 1 ,5 print(a,b) # 1, 1
-
子作用域只能找到父级作用域中的变量的值,不能重新为赋值父级作用域的变量赋值.
-
例外,特别: global 变量名,强制把全局的变量赋值
a = b = 1 def func(): global b b = 5 # 更改全局变量b = 5 print(a,b) func() # 1 ,5 print(a,b) # 1, 5
-
nonlocal ,强制把父级的变量赋值 ,一级一级向上找寻,不找全局域.找不到则报错.
a = b = 1 def func(): nonlocal b b = 5 # 更改父级变量,如果找不到,再到父级的父级找寻,一直找到全局域之前(不包含全局域) print(a,b) func() #会报错,父级就是全局域,nonlocal不包含全局域,故会报错,找不到b print(a,b) a = b = 1 def func(): a = 3 b = 99 print(a,b) def func1(): nonlocal b b = 88 print(a,b) func1() func() print(a,b)
-
补充: 全局变量大写
-
-
递归函数(效率低下,不推荐)
# 递归的返回值 ##函数在内部调用自己---> 递归函数 # 效率很低,python对栈,即函数递归的次数有限制-->1000次 # 尽量不要使用 递归函数 # 递归的返回值 def func(a): if a == 5: return 100000 result = func(a+1) + 10 v = func(1) name = 'alex' def func(): def inner(): print(name) return inner v =func()
def func(i): print(i) func(i+1) func(1) 递归次数有限制 1000次
5.2.7执行函数
-
函数不被调用,内部代码永远不执行。
def func(): return i func_list = [] for i in range(10): func_list.append(func) print(i) # 9 v1 = func_list[4]() v2 = func_list[0]()
func_list = [] for i in range(10): # func_list.append(lambda :x) # 函数不被调用,内部永远不执行(不知道是什么。) func_list.append(lambda :i) # 函数不被调用,内部永远不执行(不知道是什么。) print(func_list) func_list[2]()=
-
执行函数时,会新创建一块内存保存自己函数执行的信息 => 闭包
def base(): return i def func(arg): def inner(): return arg return inner base_list = [] # [base,base,] func_list = [] # [由第一次执行func函数的内存地址,内部arg=0 创建的inner函数,有arg=1的inner函数 ] for i in range(10): # i = 0 ,1 base_list.append(base) func_list.append(func(i)) # 1. base_list 和 func_list中分别保存的是什么? """ base_list中存储都是base函数。 func_list中存储的是inner函数,特别要说的是每个inner是在不同的地址创建。 """ # 2. 如果循环打印什么? for item in base_list: v = item() # 执行base函数 print(v) # 都是9 for data in func_list: v = data() print(v) # 0 1 2 3 4
-
总结:
- 传参:位置参数 > 关键字参数
- 函数不被调用,内部代码永远不执行。
- 每次调用函数时,都会为此次调用开辟一块内存,内存可以保存自己以后想要用的值。
- 函数是作用域,如果自己作用域中没有,则往上级作用域找。
5.3 函数高阶
5.3.1 函数中高阶(重点)
-
函数的变换
def func(): print('小米手机真的好') # 这里func--------->指向函数的内存地址 print(id(func)) # 33627808 a = '小米手机真的好' print(id(a)) # 35196048 # 函数的名字和变量类似,有类似的指向关系.变量指向一块内存地址放置数据,函数也指向一块内存地址放置数据
-
函数名当做变量使用
def func(): print('小米手机真的好') print(id(func)) # 33627808 a = '小米手机真的好' print(id(a)) # 35196048 fuck_world = func print(id(fuck_world)) #33627808 ,2者内存地址一致. fuck_world() # 调用函数,打印'小米手机真的好'
-
函数名作为列表/元组/字典元素(是不可变类似,可以做字典的键<-------->str)
def func1(): print('快活啊') func_list = [func1, func1, func1] func_list[0]() func_list[1]() func_list[2]() # 类似的用法,调用函数运行,注意: 加上括号就可以运行该函数了 for item in func_list: v = item() # 函数语句没有retun,返回值默认为None print(v)
-
函数可以当作参数进行传递 --->构造字典和函数的对应关系,避免重复if else
def func3(arg): v = arg() print(arg()) print(arg) def show(): return 999 func3(show) # 调用函数,把show函数当做参数使用.
-
面试题相关
def func3(): print('话费查询') def func4(): print('流量办理') def func5(): print('充值') def func6(): print('人工服务') info = { 'k1':func3, 'k2':func4, 'k3':func5, 'k4':func6 } content = input('请输入你要办理的业务:') function_name = info.get(content) function_name() # 运用字典调用函数
-
-
函数可以做返回值
def func(): print('name') def show() return func # ****************** v = show() v() # 执行打印name #******************** show()() # 相当于show()()
-
函数的闭包--->封装了值,内层函数调用才是闭包,缺一不可 .
-
闭包概念:为函数创建一块区域并为其维护自己数据,以后执行时方便调用。【应用场景:装饰器 / SQLAlchemy源码】
name = 'oldboy' def bar(name): def inner(): print(name) return inner v1 = bar('alex') # { name=alex, inner } # 闭包,为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。 v2 = bar('eric') # { name=eric, inner } ,2者不干扰运行. v1() v2() # 不是闭包 def func1(name): def inner(): return 123 return inner # 是闭包:封装值 + 内层函数需要使用。 def func2(name): def inner(): print(name) return 123 return inner
-
-
数据类型中那些有返回值
# 无返回值 v = [11,22,33] v.append(99) # 无返回值 # 仅有返回值: v = "alex" result = v.split('l') v = {'k1':'v2'} result1 = v.get('k1') result2 = v.keys() # 有返回+修改数据 (少) v = [11,22,33] result = v.pop()
-
常用数据类型方法返回值(重点)
- str - strip,返回字符串 - split,返回列表 - replace,返回字符串 - join,返回字符串。 - list - append,无 - insert,无 - pop,返回要删除的数据 - remove,无 - find/index,返回索引的位置。 - dict - get - keys - values - items
5.3. 2 lambda函数(匿名函数)
用于表示非常简单的函数,就如三元运算和if 语句一样.
-
lambad函数只能用一行代码
# lambda表达式,为了解决简单函数的情况,如: def func(a1,a2): return a1 + 100 func = lambda a1,a2: a1+100 # 2者等价,注意冒号后接代码,自动return
-
应用
func = lambda a,b:a if a > b else b t = func(1,5) print(t) # 求2个数里面较大的数 # 练习题1 USER_LIST = [] def func0(x): v = USER_LIST.append(x) return v result = func0('alex') print(result) # 练习题2 def func0(x): v = x.strip() return v result = func0(' alex ') print(result) ############## 总结:列表所有方法基本上都是返回None;字符串的所有方法基本上都是返回新值
5.4 python内置函数简介
5.4.1自定义函数
5.4.2内置函数
-
输入输出print input
-
强制转换类型
- dict()
- list()
- tuple()
- int()
- str()
- bool()
- set()
-
其他
- len
- open
- range
- id
- type
-
数学相关
-
abs 求绝对值
-
float ,转换为浮点型(小数)
-
max /min
-
sum 求和
-
divmod ,获取2数字相除的商和余数
-
pow ,指数函数,获取指数
v = pow(2,5) print(v) # 2^5 = 32
-
round函数,四舍五入函数
v= round(1.24879,2) #小数点后取2位 print(v) # 1.25 ############################################## # 注意:由于计算机精度问题,round函数可能会出错 round(2.355,2) # 算得的是 2.35 ,py版本3.6.8
-
-
编码相关
-
chr() ,将十进制转化unicode编码中对应的字符串
v =chr(152) print(v) i = 1 while i < 1000: print(chr(i)) i += 1
-
ord(), 根据字符在unicode编码的对应关系,找到对应的十进制.
v= ord("字") # 一次只能索引一个字符 print(v) content = """一天,我正在路上走着,突然一声 雄浑有力的声音传进我的耳朵里。""" for i in content: print(ord(i))
-
应用: 随机验证码(重点)
import random # 调用随机数函数 def get_random_code(length=6): data = [] for i in range(length): v = random.randint(65,90) # 65-90对应的是ABC-----Z data.append(chr(v) return ''.join(data) code = get_random_code() print(code)
-
-
进制转换
-
bin() 10进制转为2进制 ,''0b"
-
oct() 10进制转为8进制 ." 0o"
-
hex() 10进制转为16进制 ."0x"
-
int() 把````数转为10进制数 ,base默认为10 ,转二进制数base = 2,base = 8, base = 16
num= 192 n1 = bin(num) n2 = oct(num) n3 - hex(num) print(n1,n2,n3)
# 二进制转化成十进制 v1 = '0b1101' result = int(v1,base=2) print(result) # 八进制转化成十进制 v1 = '0o1101' result = int(v1,base=8) print(result) # 十六进制转化成十进制 v1 = '0x1101' result = int(v1,base=16) print(result) # 注意,转换时0b 0o 0x可以不用加
-
5.4.3 高级函数(必考)
-
map() 循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行的结果保存到新的列表中,并返回。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
content = [11,22,33,44,55,66,77,88,99] t = map(lambda x: x*x,content) print(list(t)) #列表元素的个数是相同的
-
filter(筛选/过滤)filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
content = [11,0,33,55,66,77,88,99] t = filter(lambda x: x < 50,content) print(list(t)) #列表元素的个数是相同的
-
reduce()reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
import functools t = [3,2,3,4,5,6,8,9] v = functools.reduce(lambda x,y: x ** y,t) print(v)
注意: 在py3中,reduce的函数移到了functools模组,要用这个功能,必须 import functools
5.5 装饰器(重点)
装饰器:在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能。
5.5.1装饰器
示例:
# #########################################
def func(arg):
def inner():
arg()
return inner
def f1():
print(123)
v1 = func(f1)
v1()
# ###########################################
def func(arg):
def inner():
arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1) # 运行func(),创建一块空间,定义 inner函数.返回值 inner
result = v1() # 执行inner函数 / f1含函数 -> 123
print(result) # None
# ###########################################
def func(arg):
def inner():
return arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1)
result = v1() # 执行inner函数 / f1含函数 -> 123
print(result) # 666
示例:
# #########################################
def func(arg):
def inner():
arg()
return inner
def f1():
print(123)
v1 = func(f1)
v1()
# ###########################################
def func(arg):
def inner():
arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1) # 运行func(),创建一块空间,定义 inner函数.返回值 inner
result = v1() # 执行inner函数 / f1含函数 -> 123
print(result) # None
# ###########################################
def func(arg):
def inner():
return arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1)
result = v1() # 执行inner函数 / f1含函数 -> 123
print(result) # 666
5.5.2装饰器的本质
def func(arg):
def inner():
print('before')
v = arg()
print('after')
return v
return inner
def index():
print('123')
return '666'
index = func(index) # --->指向inner函数.
index() # ---> 运行inner函数-->运行打印'before'/原index函数()/运行打印'after'
-
装饰器的格式
def func(arg): def inner(): v = arg() return v return inner # 第一步:执行func函数并将下面的函数参数传递,相当于:func(index) # 第二步:将func的返回值重新赋值给下面的函数名。 index = func(index) @func # @func等价于上面2步 def index(): print(123) return 666 print(index)
-
应用
# 计算函数执行时间 def wrapper(func): def inner(): start_time = time.time() v = func() end_time = time.time() print(end_time-start_time) return v return inner @wrapper def func1(): print(123454987+865484) func1() # --->自动启动装饰器
-
总结
-
目的:在不改变原函数的基础上,再函数执行前后自定义功能。
-
编写装饰器 和应用
# 装饰器的编写 def x(func): def y(): # 前 ret = func() # 后 return ret return y # 装饰器的应用 @x def index(): return 10 @x def manage(): pass # 执行函数,自动触发装饰器了 v = index() print(v) @xx # index = xx(index) def index(): pass index()
-
应用场景:想要为函数扩展功能时,可以选择用装饰器。
-
-
重点内容装饰器(重点)
def 外层函数(参数): def 内层函数(*args,**kwargs): # -->无论被装饰函数有多少个参数,都能用万能参数传入. return 参数(*args,**kwargs) return 内层函数 @外层函数 def index(): pass index() # --->自动调用装饰器
-
装饰器建议写法
def x1(func): def inner(*args,**kwargs): data = func(*args,**kwargs) return data return inner def x1(func): def inner(*args,**kwargs): print('调用原函数之前') data = func(*args,**kwargs) # 执行原函数并获取返回值 print('调用员函数之后') return data return inner @x1 def index(): print(123) index()
5.5.3带参数的装饰器
-
基本格式
def wrapper(func): def inner(*args,**kwargs): v = func() return v return i
-
装饰器加上参数(外层函数必须以函数名作为参数,要给装饰器加上参数,在外层再套一层函数)
def super_wrapper(counter): # counter 装饰器参数 print(123) def wrapper(func): print(456) def inner(*args, **kwargs): # 参数统一的目的是为了给原来的index函数传参 data = [] for i in range(counter): v = func(*args, **kwargs) # # 参数统一的目的是为了给原来的index函数传参 data.append(v) return data return inner return wrapper @super_wrapper(9): # 这时已经打印 123 456 # # func = 原来的index函数u # index = inner # 已经运行super_wrapper函数和wrapper函数 def index(i): print(i) return i+1000 print(index(456)) # 调用index函数(带装饰器)
# ################## 普通装饰器 ##################### def wrapper(func): def inner(*args,**kwargs): print('调用原函数之前') data = func(*args,**kwargs) # 执行原函数并获取返回值 print('调用员函数之后') return data return inner @wrapper def index(): pass # ################## 带参数装饰器 ##################### def x(counter): def wrapper(func): def inner(*args,**kwargs): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @x(9) def index(): pass
- 基本装饰器更重要8成
- 带参数的装饰器2成
- 装饰器本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外的功能 ,装饰器的返回值也是一个函数对象,她有很多的应用场景,比如:插入日志,事物处理,缓存,权限装饰器就是为已经存在的对象 添加额外功能
5.6 推导式
5.6.1列表推导式
-
目的: 为了方便生成一个列表
#####基本格式##### v1 = [i for i in range(9)] # 创建列表10个元素 v2 = [i for i in range(9) if i > 5] #对每个i,判断if i > 5,为真则添加到列表中 v3 = [99 if i > 55 else 66 for i in range(9)] # 三木运算 """ v1 = [i for i in 可迭代对象 ] v2 = [i for i in 可迭代对象 if 条件 ] # 条件为true才进行append """ ######函数###### def func(): return i v6 = [func for i in range(10)] # 10个func组成的列表,内存地址一致. result = v6[5]() # 运行报错,提示 i 没有被定义, v7 = [lambda :i for i in range(10)] # 10个lambda函数组成的列表,内存地址不一致,有10个 result = v7[5]() # 运行不报错,输出result 为 9 ## 第一个func和列表生成器函数作用域都在第一级,找不到 i ## 第二个lambda上级是列表生成器函数作用域 ###面试题 v8 = [lambda x:x*i for i in range(10)] # 新浪微博面试题 # 1.请问 v8 是什么? 10个lambda函数,内存地址不一样,构建的列表 # 2.请问 v8[0](2) 的结果是什么? i 在列表生成式函数作用域里面,lambda是奇子集,i = 9,输出18 ### 面试题 def num(): return [lambda x:i*x for i in range(4)] # num() -> [函数,函数,函数,函数] print([ m(2) for m in num() ]) # [6,6,6,6]
5.6.2集合推导式
- 和列表推导式类似,这不再赘述.
5.6.3字典推导式
v1 = { 'k'+str(i):i for i in range(10) } # 和列表类似,中间有:区分键和值.
5.7 迭代器
5.7.1自己不用写迭代器,只.
# 一一展示列表中的元素
# 1.for 循环 2. while + 索引 + 计数器
# 使用迭代器--->对 某种对象(str/list/tuple/dict/set类创建的对象)-可迭代对象中的元素进行逐一获取,表象:具有`__next__`方法且每次调用都获取可迭代对象中的元素(从前到后一个一个获取)。
# 可被for 循环的---> 可迭代对象
#***************************************************************#
v1 = [1,2,3,4]
v2 = iter(v1) # --->v2是一个迭代器
#或者 v2 = v1.__iter__()
# 迭代器想要获取每个值:-->反复调用
while 1 :
val = v1.__next__()
print(val)
##### ********* ######
v3 = "alex"
v4 = iter(v1)
while True:
try:
val = v2.__next__()
print(val)
except Exception as e:
break
# 直到报错:StopIteration错误,表示已经迭代完毕。
-
判定是否是迭代器 --> 内部是否有
__next__方法
-
for 循环---->为这简便有了for 循环
v1 = [11,22,33,44] # 1.内部会将v1转换成迭代器 # 2.内部反复执行 迭代器.__next__() # 3.取完不报错 for item in v1: print(item)
5.7.2可迭代对象
-
内部具有
__iter__()
方法且返回一个迭代器。(*)v1 = [11,22,33,44] result = v1.__iter__()
-
可以被for循环
5.7.3 小结
- 迭代器,对可迭代对象中的元素进行逐一获取,迭代器对象的内部都有一个 __next__方法,用于以一个个获取数据。
- 可迭代对象,可以被for循环且此类对象中都有 __iter__方法且要返回一个迭代器(生成器)。
5.8 生成器
生成器(变异函数---->特殊的迭代器)
生成器,函数内部有yield则就是生成器函数,调用函数则返回一个生成器,循环生成器时,则函数内部代码才会执行。
-
函数样式
# 函数 def func(): return 123 func()
-
生成器
# 生成器函数(内部是否包含yield)---->只要有yeild就是生成器,不论是否有return def func(): print('F1') yield 1 print('F2') yield 2 print('F3') yield 100 print('F4') # 函数内部代码不会执行,返回一个 生成器对象 。 v1 = func() # 生成器是可以被for循环,一旦开始循环那么函数内部代码就会开始执行。 for item in v1: print(item)
-
总结:函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会执行,每次循环都会获取yield返回的值
def func(): count = 1 while 1 : yield count count += 1 if count == 100 : return val = func() # --->调用生成器函数 ---->返回值时一个生成器 --->内部代码没有执行 for item in val : print(item) # 此时才执行生成器内部代码,并yield.就冻结,直到下次再继续运行.
-
示例 读文件
def func(): """ 分批去读取文件中的内容,将文件的内容返回给调用者。 """ cursor = 0 while 1 : f = open(r'D:Python学习pythons21day16goods.txt','r',encoding='utf-8-sig') f.seek(cursor) data_list = [] # 光标移到最前 for i in range(10): line = f.readline() # 一次读一行 if not line: return data_list.append(line) cursor = f.tell() #获取光标 f.close() # 关闭与redis的连接 for row in data_list: yield row for itemm in func(): p = input('qingsr123456498') print(itemm)
-
5.8.1 range和 xrange区别
- range 函数说明:range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。
- xrange 函数说明:用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。
- py3中只有range,是生成器,
5.8.2 生成器推导式
# def func():
# for i in range(10):
# yield i
# v2 = func()
v2 = (i for i in range(10)) # 生成器推导式,创建了一个生成器,内部循环为执行。
# 没有元组推导式,加括号是生成器推导式
def my_range(counter):
for i in range(counter):
yield i
# 生成器函数
# # 面试题:请比较 [i for i in range(10)] 和 (i for i in range(10)) 的区别?
# 前者是列表推导式,直接在内存中生成列表[1-10],后者是生成器推导式,内部循环不执行,只有for 循环才执行.
# 示例一
# def func():
# result = []
# for i in range(10):
# result.append(i)
# return result
# v1 = func()
# for item in v1:
# print(item) # 列表推导式
# 示例二
# def func():
# for i in range(10):
# def f():
# return i
# yield f # 生成器函数
#
# v1 = func() # 生成器,内部代码不执行
# for item in v1:
# print(item()) #for 循环才执行
新人上路,请多多批评指正