day12-三大神器
一、迭代器
list1 = [19, 89, 78, 67]
result = map(lambda item: item % 10, list1)
print(result) # 迭代器,打印看不到元素
print(list(result)) # 取出来转换成列表
print(list(result)) # 取出来用了后元素就没有了,不会再放回去
1.什么是迭代器(iter)
迭代器是容器型数据类型(序列),迭代器无法直接获取所有元素,也不能统计元素个数。
获取迭代器中的元素是会导致这个元素从迭代器中消失。(元素取一个就少一个)
2.创建迭代器
创建迭代器只有两种方法:1)将其他序列转换成迭代器 2)创建生成器
iter1 = iter('abc')
print(iter1) # <str_iterator object at 0x0000000001DF6970>
iter2 = iter([10, 20, 30, 40])
print(iter2)
iter3 = iter([{'a': 10}, {'b': 20}])
print(iter3)
3.获取迭代器中的元素
1)获取单个元素:next(迭代器)
iter1 = iter('abc')
print(next(iter1)) # a
print(next(iter1)) # b
print(next(iter1)) # c
# print(next(iter1)) # StopIteration
iter3 = iter([{'a': 10}, {'b': 20}])
print(next(iter3)) # {'a': 10}
print(next(iter3)) # {'b': 20}
2)遍历
iter2 = iter([10, 20, 30, 40])
for x in iter2:
print(f'x:{x}')
for x in iter2:
print(f'x:{x}') # 空
二、生成器
1.生成器
生成器从获取数据和保存特点来看,就是迭代器。
生成器保存数据的本质不是保存数据本身,而是保存产生数据的算法。
2.创建生成器
调用带有yield关键字的函数就可以得到一个生成器
调用带有yield关键字的函数的时候不会执行函数体,也不会获取函数返回值,只是单纯的创建一个生成器
def func1():
yield
print('=====')
return 100
result = func1()
print(result)
3.确定生成器的元素 - 生成器可以创造的数据
一个生成器能产生多少个数据就看这个生成器对应的函数,执行完函数会遇到几次yield。
每次遇到yield的时候yield后面的数据就是产生的数据
def func2():
yield 100
yield 200
yield 300
result = func2()
print(next(result)) # 100
print(next(result)) # 200
print(next(result)) # 300
4.生成器产生数据的原理
当通过生成器对象获取元素(不管以什么样的方式获取)的时候,系统会自动执行生成器对应的函数,执行函数的时候不会直接将整个函数执行完
而且每次在执行yield的时候就会停下来,并且将yield后面的数据作为结果返回。
下次再获取元素的是从上次结束的位置开始执行
def func3():
print('11111111')
yield 100
print('222222')
yield 200
print('3333333')
yield 300
print('4444444')
result = func3()
print(next(result))
print('!!!!!!!!!!!!!!!!!')
print(next(result))
print('!!!!!!!!!!!!!!!!!')
print(next(result))
for x in result:
print(x)
def func4():
yield print('abc')
result = func4()
print(next(result)) # None
def func4():
yield 'abc'
result = func4()
print(next(result))
def func5():
yield 10
yield 20
yield 30
yield 40
print(next(func5())) # 10
print(next(func5())) # 10
result = func5()
print(next(result)) # 10
print(next(result)) # 20
# 写一个创建学生学号的生成器,要求产生的学号前缀是python,后面是指定范围的值
# 26 ~ 56 ->python0026 ~ python0056
def s_num(subject='python', start=26, end=56):
for x in range(start, end+1):
yield f'{subject}{str(x).zfill(4)}'
result = s_num()
print(next(result))
print(next(result))
for _ in range(3):
print(next(result))
java = s_num('java', 1, 50)
print(next(java))
三、装饰器(了解)
1.什么是装饰器
装饰器 = 实参高阶函数 + 返回值高阶函数 + 糖语法 (装饰器的本质是函数)
作用:给已经定义好的函数添加功能
import time
def func1():
start = time.time()
print('hello world!')
end = time.time()
print(f'函数执行时间:{end-start}')
func1()
def func2(a, b):
start = time.time()
print(a + b)
end = time.time()
print(f'函数执行时间:{end-start}')
func2(10, 9)
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 func3():
print('hello world!')
func3()
2.无参装饰器的实现方法
装饰器的工作原理:将需要添加功能的函数传给装饰器,装饰器创建一个保留原函数功能并且添加新功能的一个新的函数
将添加完功能的新函数返回,最后用新的函数替换原来的函数。
装饰器的套路:
def 函数名1(参数1:function):
def 函数名2(*args, **kwargs):
添加新的功能
result = 参数1(*args, **kwargs)
return result
return 函数2
函数名1 - 装饰器功能对应的名字
参数1 - 类型是function,指向需要添加功能的原函数,习惯命名成:fn
函数名2 - 指向添加完功能的新函数,习惯命名成:new_fn
def 装饰器名(fn):
def new_fn(*args, **kwargs):
新功能
result = fn(*args, **kwargs)
return result
return new_fn
# 1.写一个装饰器在函数调用结束的时候打印‘end'
def add_end_message(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
print('end')
return result
return new_fn
# 2.写一个装饰器将原函数的返回值加100
def add_100(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
if type(result) in (int, float):
return result + 100
return result
return new_fn
# @add_end_message
@add_100
def func3(num: int):
sum1 = 1
for x in range(1, num+1):
sum1 *= x
return sum1
x = func3(4)
print(x)
# 练习:写一个装饰器,将函数的返回值变成字符串
def exchange_str(fn):
def new_fn(*args, **kwargs):
result = fn(*args, **kwargs)
return str(result)
return new_fn
@exchange_str
def func3(num: int):
sum1 = 1
for x in range(1, num+1):
sum1 *= x
return sum1
print(type(func3(4)))
@exchange_str
def func4():
return 'hello world!'
print(func4())
四、递归
1.递归函数
在定义函数的时候调用函数本身,这种函数就是递归函数
理论上,循环能做的事情递归都可以做。(能用循环实现就不要用递归)
注意:使用递归解决循环问题的时候,内存和cpu的消耗会随着循环次数的增加而不断增加
def fn():
print('hello')
fn()
2.使用递归的套路
第一步:找临界值,在临界值的位置结束函数(相当于循环结束的条件)
第二步:找关系,找上一次循环结束的结果和当次循环结束的结果的关系
第三步:假设函数功能已经实现,通过关系用f(n-1)实现f(n)的功能
# 1.计算1+2+3+...+100
def sum1(n):
# 临界值
if n == 1:
return 1
return sum(n-1) + n
# 关系:sum1(n)和sum1(n-1)
# sum(n) = sum(n-1) + n
# 1, 1, 2, 3, 5, 8, 13....
def num(n):
if n == 1 or n == 2:
return 1
return num(n-1) + num(n-2)
print(num(3))
# 2.打印下面的图形
"""
n=3
*
**
***
n=4
*
**
***
****
"""
def star(n):
if n == 1:
print('*')
return
star(n-1)
print("*"*n)