python基础语法9 生成器,面向对象编程思想,三元表达式,列表生成式,生成器表达式(生成式),匿名函数,内置函数
生成器
1.什么是生成器?
生成的工具。
生成器是一个 "自定义" 的迭代器, 本质上是一个迭代器。
2.如何实现生成器
但凡在函数内部定义了的yield,
调用函数时,函数体代码不会执行,
会返回一个结果,该结果就是一个生成器。
yield:
每一次yield都会往生成器对象中添加一个值。
- yield只能在函数内部定义
- yield可以保存函数的暂停状态
yield与return:
相同点:
返回值的个数都是无限制的。
不同点:
return只能返回一次值,yield可以返回多个值,默认是元组,可以修改返回类型
自定义的迭代器 def func(): print('开始准备下蛋') print('1---火鸡蛋1') yield '火鸡蛋1' print('2---火鸡蛋2') yield '火鸡蛋2' print('3---火鸡蛋3') yield '火鸡蛋3' print('取最后一个蛋,查看是否有') res是迭代器对象 res = func() 当我们通过__next__取值时,才会执行函数体代码。 next(迭代器对象) print(next(res)) print(next(res)) print(next(res)) 迭代器对象.__next__() print(res.__next__()) print(res.__next__()) print(res.__next__()) print(res.__next__()) # StopIteration报错
自定义range功能,创建一个自定义生成器
# 循环10次 # for i in range(1, 11): # # print(i) # 1—10 # python2: range(1, 5) ---> [1, 2, 3, 4] # python3: range(1, 5) ---> range对象 ---> 生成器 ---> 迭代器 # res = range(1, 5) # print(res) # 自定义range功能,创建一个自定义的生成器 # (1, 3) # start--> 1 , end---> 5, move=2 def my_range(start, end, move=1): # while start < end: yield start start += move # g_range = my_range(1, 5) # print(g_range) # # for line in g_range: # print(line) for line in my_range(1, 5, 2): print(line)
面向过程编程
思想!!!
面向过程编程是一门编程思想。
面向 过程 编程:
核心是 '过程' 二字,过程 指的是一种解决问题的步骤,即先干什么再干什么
基于该编程思想编写程序,就好比在设计一条工厂流水线,一种机械式的思维方式。
优点:
将复杂的问题流程化,进而简单化
缺点:
若修改当前程序设计的某一部分, 会导致其他部分同时需要修改, 扩展性差。
牵一发而动全身,扩展性差。
三元表达式
可以将if...else...分支变成一行。
语法:
条件成立返回左边的值 if 判断条件 else 条件不成立返回右边的值
def max2(num1, num2): res = num1 if num1 > num2 else num2 return res res = max2(3, 2) print(res) # 需求: 让用户输入用户名,输入的用户如果不是tank,为其后缀添加_DSB username = input('请输入用户名:').strip() new_username = username if username == 'tank' else username + '_DSB' print(new_username)
列表生成式
可以一行实现生成列表。
语法:
list = [取出的每一个值、任意值 for 可迭代对象中取出的每一个值 in 可迭代对象]
# for的右边是循环次数,并且可以取出可迭代对象中每一个值
# for的左边可以为当前列表添加值
list = [值 for 可迭代对象中取出的每一个值 in 可迭代对象]
list = [值 for 可迭代对象中取出的每一个值 in 可迭代对象 if 判断]
# 列表生成式 list1 = [f'1{line}' for line in range(1, 101)] print(list1) #Demo: 将name_list列表中的每一个人后缀都添加_dsb name_list = ['jason', '饼哥(大脸)', 'sean', 'egon'] new_name_list = [name + '_dsb' for name in name_list] print(new_name_list) #将name_list列表中的tank过滤掉,其他人后缀都添加_dsb name_list = ['jason', '饼哥(大脸)', 'sean', 'egon', 'tank'] new_name_list = [name + '_dsb' for name in name_list if not name == 'tank'] print(new_name_list)
生成器表达式(生成式)
- 列表生成式: 若数据量小时采用
[line for line in range(1, 6)] ---> [1, 2, 3, 4, 5]
优点:
可以依赖于索引取值,取值方便
缺点:
浪费资源
- 生成器生成式: 若数据量过大时采用
() ---> 返回生成器
(line for line in range(1, 6)) ---> g生成器(1, 2, 3, 4, 5)
优点:
节省资源
缺点:
取值不方便
# 生成一个有1000个值的生成器 g = (line for line in range(1, 1000001)) # <generator object <genexpr> at 0x00000203262318E0> print(g) # 列表生成式实现 list1 = [line for line in range(1, 1000001)] print(list1) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10...]
匿名函数:
无名字的函数
# :左边是参数, 右边是返回值
lambda :
PS: 原因,因为没有名字,函数的调用 函数名 + ()
匿名函数需要一次性使用。
注意: 匿名函数单独使用毫无意义,它必须配合 “内置函数” 一起使用的才有意义。
有名函数:
有名字的函数
func = lambda x,y:x if x > y else y print(func(2,6)) #6 calc = lambda x,y:x**y print(calc(2,5)) #32
#按年龄排序 l=[{'name':'alex','age':84},{'name':'oldboy','age':73}, {'name':'egon','age':18}] l.sort(key=lambda x:x['age']) print(l) # [{'name': 'egon', 'age': 18}, {'name': 'oldboy', 'age': 73}, {'name': 'alex', 'age': 84}]
内置函数:
range()
print()
len()
# python内部提供的内置方法
max, min, sorted, map, filter
max: 获取可迭代对象中最大值
min: 获取可迭代对象中最小值
sorted: 对可迭代对象进行排序
默认是: 升序
reverse=True: 降序
map: 映射
reduce: 合并
filter: 过滤
# max求最大值 max(可迭代对象) list1 = [1, 2, 3, 4, 5] # max内部会将list1中的通过for取出每一个值,并且进行判断 print(max(list1)) # dict1 = { 'tank': 1000, 'egon': 500, 'sean': 200, 'jason': 500 } # 获取dict1中薪资最大的人的名字 # 字符串的比较: ASCII print(max(dict1, key=lambda x: dict1[x])) #tank 因为以索引判断,所以key就是索引,参数x为索引
# 获取dict1中薪资最小的人的名字
print(min(dict1, key=lambda x:dict1[x]))
# sorted: 默认升序(从小到大) reverse:反转 reverse默认是False list1 = [10, 2, 3, 4, 5] print(sorted(list1)) # reverse=True--> 降序 print(sorted(list1, reverse=True)) dict1 = { 'tank': 100, 'egon': 500, 'sean': 200, 'jason': 50 } # new_list = ['egon', 'sean', 'tank', 'jason'] new_list = sorted(dict1, key=lambda x: dict1[x], reverse=True) print(new_list)
map()
map(函数地址, 可迭代对象) ---> map对象
map会将可迭代对象中的每一个值进行修改,然后映射一个map对象中,
可以再将map对象转换成列表/元组。
注意: 只能转一次。
name_list = ['egon', 'jason', 'sean', '大饼', 'tank'] map_obj = map(lambda name: name + '喜欢吃生蚝' if name == 'tank' else name + 'DJB', name_list) print(map_obj) # map_obj ---> list/tuple print(list(map_obj)) # map_obj ---> 生成器(迭代器) ---> 用完后,不能再取了 print(tuple(map_obj)) # map对象只能调用一次,第二次返回空 # 结果 # <map object at 0x00000000021CF4A8> # ['egonDJB', 'jasonDJB', 'seanDJB', '大饼DJB', 'tank喜欢吃生蚝'] # ()
list1=[1,2,3,4,5] res=map(lambda x:x**2,list1) print(list(res)) # [1, 4, 9, 16, 25] def square(x): return x**2 ---------------------------------------- list1=[1,2,3,4,5] res=map(square,list1) print(list(res)) # [1, 4, 9, 16, 25]
reduce() # 函数必须接受两个参数
reduce(函数地址, 可迭代对象, 默认为0)
reduce(函数地址, 可迭代对象, 初始值)
# reduce from functools import reduce #需要导入模块 # 每次从可迭代对象中获取两个值进行合并, # 初始值: 执行reduce函数时,都是从初始值开始合并 reduce(lambda x, y: x + y, range(1, 101), 0)# 先算x=0 + y=1,和为x再+2,和再+3...+100 # 需求: 求1——100的和 # 普通 init = 1000 for line in range(1, 101): init += line print(init) # 5050 # reduce res = reduce(lambda x, y: x + y, range(1, 101), 1000)# 先算x=1000 + y=1,和为x再+2,和再+3...+100 print(res) # 6050
filter()
filter(函数地址, 可迭代对象) --> filter 对象
# filter name_list = ['egon_dsb', 'jason_dsb', 'sean_dsb', '大饼_dsb', 'tank'] # filter_obj = filter(lambda x: x, name_list) # 将后缀为_dsb的名字 “过滤出来” # filter会将函数中返回的结果为True 对应 的参数值 “过滤出来” # 过滤出来的值会添加到 filter对象中 filter_obj = filter(lambda name: name.endswith('_dsb'), name_list) #是否结尾为'_dsb',如果为true,返回那个值 print(filter_obj) #<filter object at 0x0000000001E4C5C0> print(list(filter_obj)) # ['egon_dsb', 'jason_dsb', 'sean_dsb', '大饼_dsb'] # print(tuple(filter_obj)) ---------------------------------------------------------------- name_list = ['egon_dsb', 'jason_dsb', 'sean_dsb', '大饼_dsb', 'tank'] filter_obj = filter(lambda x:x[-3:] != 'dsb',name_list) print(filter_obj) print(list(filter_obj)) # ['tank']