文章目录
【总结】Python基础三大神器(2022.4.26)
1. 迭代器
1.1 什么是迭代器
迭代器是容器:程序中无法直接创建一个迭代器,只能把别的序列转换成迭代器
迭代器特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;
获取元素的时候只能一个一个的取,每次只能获取最前面的哪个元素,且元素取一个就少一个
#如何得到一个迭代器
i1 = iter('abc123')
print(i1) # 返回 <str_iterator object at 0x000001F7FF2C8BE0>
i2 = iter([10,23,45])
print(i2) # 返回 <list_iterator object at 0x0000023C66058430>
i3 = iter({'a':10, 'b':20, 'c':30})
print(i3) # 返回 <dict_keyiterator object at 0x0000023C66044720>
1.2 迭代器查操作 - 获取迭代器元素
注意:不管以什么样的方式获取到了迭代器某个元素,那么这个元素一定会从迭代器中消失。
获取方式:
A. 查单个:next(迭代器) - 获取迭代器中最前面的那个元素
print(next(i1)) # 'a'
print(next(i1)) # 'b'
print(next(i2)) # 10
print(next(i2)) # 23
print(next(i2)) # 45
# print(next(i2)) # 报错!数据已取完:StopIteration
B. 遍历
i4 = iter('hello')
for x in i4:
print('x:', x)
# print(next(i4)) # 报错!数据已遍历 StopIteration
2. 生成器
2.1 什么是生成器
生成器也是容器,其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法。生成器获取数据的方式和特点和迭代器一样。
2.2 创建生成器
方法:调用一个带有yield关键字的函数就可以得到一个生成器对象
请看例子:
# 创建一个普通函数,观察其返回值
def func1():
print('++++')
print('====')
return 100
result = func1()
print('result:',result) # result: 100
# 创建一个带有yield关键字的函数,观察其返回值
def func1():
yield
print('++++')
print('====')
return 100
gen1 = func1()
print('result:',gen1) # result: <generator object func1 at 0x00000246ED5DC9E0>
2.3 如何控制生成器产生数据的个数和值
一个生成器产生的个数和值由创建生成器调用的那个函数的函数体在执行的时候会遇到几次yield以及每次yield后面的值来决定
个数:由遇到的yield的次数决定
值:由yield后面的数据决定
def create1():
yield 100
yield 200
yield 300
gen2 = create1()
# print(list(gen2)) # [100, 200, 300]
print(next(gen2)) # 100
print(next(gen2)) # 200
print(next(gen2)) # 300
# print(next(gen2)) # StopIteration
def create2():
x = 0
while True:
yield x
x += 1
gen3 = create2()
print('gen3:', gen3)
print(next(gen3))
for _ in range(10):
print(next(gen3))
#遍历后已将值取完
# print(next(gen2)) # StopIteration
# 练习:写一个生成器可以创建某个python班级的学生的学号,学号的范围是:python0001~python1000
def study_id(suject):
for x in range(1,1001):
yield f'{suject}{x:0>4}'
python_id = study_id('python')
java_id = study_id('java')
print(next(python_id)) # python0001
print(next(java_id)) # java0001
2.4 生成器创建数据的原理
每次获取生成器的数据的时候,就会取执行创建这个生成器的函数体,但是每次执行都只会执行到yield就停下来(将函数体分段执行)。
##例1
def func2():
print('=======')
yield 100
print('+++++++')
yield 200
print('!!!!!!!')
yield 300
gen4 = func2()
print('第1次取值:',next(gen4))
# =======
# 取第1次值: 100
print('第2次取值:',next(gen4))
# +++++++
# 取第2次值: 200
print('第3次取值:',next(gen4))
# !!!!!!!
# 取第3次值: 300
##例1
result = map(lambda item: item*2, 'abc')
print(result, next(result)) # <map object at 0x000001F0E6A2BFD0> aa
print(result, next(result)) # <map object at 0x000001F0E6A2BFD0> bb
print(result, next(result)) # <map object at 0x000001F0E6A2BFD0> cc
3. 装饰器
3.1 装饰器基础
A. 什么是装饰器 - 给已经定义好的函数添加功能的工具
装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数。
B. 装饰器作用:给已定义好的函数添加功能
练习: 给函数添加功能,统计函数的执行时间
# 解决方案1:直接修改原函数
import time
def hello():
start = time.time()
print('hello world!')
end = time.time()
print(f'总时间:{end - start}')
hello()
# 解决方案2:定义一个函数来接收统计需要时间的函数
def hello():
print('hello world!')
def factorial(n=2):
s = 1
for x in range(1, n+1):
s *= x
print('阶乘:', s)
def total_time(fn, *args, **kwargs): # fn用来接收统计需要时间的函数
start = time.time()
fn(*args, **kwargs)
end = time.time()
print(f'总时间:{end - start}')
total_time(hello)
total_time(factorial,10)
# 解决方案3:使用装饰器
def total_time(fn):
def new_fn(*args, **kwargs):
start = time.time()
result = fn(*args, **kwargs)
end = time.time()
print(f'总时间:{end - start}')
return result
return new_fn
@total_time # 使用装饰器
def hello():
print('hello world!')
@total_time # 使用装饰器
def factorial(n=2):
s = 1
for x in range(1, n+1):
s *= x
print('阶乘:', s)
hello()
factorial(6)
3.2 无参装饰器
语法:
def 装饰器名(原函数): - 原函数是需要装饰的函数
def 添加完功能的新函数(*args,**kwargs): - 保留原函数功能添加新功能
调用原函数
添加新功能
return 添加完功能的新函数
语法细化:
def 装饰器名(f):
def new_f(*args,**kwargs)
result = f((*args,**kwargs)
<新增功能>
return result
return new_f
装饰器名 - 根据新增的功能来命名
# 练习1: 写一个装饰器在函数调用结束的时候打印'=====end====='
def print_end(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
print('=====end=====')
return result
return new_fn
@print_end
def hello():
print('hello world!')
hello() # hello world!v
# =====end=====
# 练习2:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍。 3 -> 300; 'abc' -> 'abc'; 1.23 -> 123
def magnify(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
if type(result) in (int, float):
return result * 100
else:
return result
return new_fn
@magnify
def return_val(data):
return data
print(return_val("123")) # 123
print(return_val(20)) # 2000
3.3 有参装饰器
有参装饰器语法细化:
def 装饰器名(参数列表):
def 无参装饰器(f)
def new_f(*args,**kwargs)
result = f((*args,**kwargs)
新增功能
return result
return new_f
return 无参装饰器
参数列表 - 看实现装饰器新增功能需不需要额外数据,需要几个
# 练习1:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍数
def magnify(n):
def temp(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
if type(result) in (int, float):
return result * n
else:
return result
return new_fn
return temp
@magnify(5)
def sum3(num1, num2):
return num1 + num2
print(sum3(10,20))
rgs, **kwargs):
result = fn(*args, **kwargs)
if type(result) in (int, float):
return result * n
else:
return result
return new_fn
return temp
@magnify(5)
def sum3(num1, num2):
return num1 + num2
print(sum3(10,20))