day12 三大神器
01迭代器
1.什么是迭代器(iter)
迭代器是容器; 程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器。
特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;获取元素的时候每次只能获取最前面的那个元素,而且元素取一个就少一个
i1 = iter('abc123')
print(i1) # <str_iterator object at 0x7f99fb98fc40>
# print(len(i1)) # 报错!
i2 = iter([10, 23, 45])
print(i2) # <list_iterator object at 0x7fd037187df0>
i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(i3) # <dict_keyiterator object at 0x7f94a11c5220>
2.查 - 获取元素
迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失
1)查单个: 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
print(list(i1)) # ['c', '1', '2', '3']
print(list(i2)) # []
i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(list(i3)) # ['a', 'b', 'c']
# print(next(i3)) # 报错!
2)遍历
i4 = iter('hello')
for x in i4:
print('x:', x)
# print(next(i4)) # 报错!
02生成器
1.什么是生成器
生成器也是容器;其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法。
生成器获取数据的方式和特点和迭代器一样。
2.创建生成器
调用一个带有yield关键字的函数就可以得到一个生成器对象
def func1():
print('++++')
print('====')
yield
return 100
gen1 = func1()
print('result:', gen1) # result: <generator object func1 at 0x7fafa3120b30>
3.控制生成器产生数据的个数和值
一个生成产生的数据的个数和值由创建生成器调用的那个函数的函数体在执行的时候会遇到几次yield以及每次yield后面的值来决定.
1)个数: 由遇到的yield的次数决定
2)值:由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))
# f'姓名:{name}, 年龄:{age}'
# 练习:写一个生成器可以创建某个Python班级的学生的学号,学号的范围是:python0001 ~ python1000
def study_id(subject):
for x in range(1, 1001):
yield f'{subject}{x:0>4}'
python_id = study_id('python')
java_id = study_id('java')
print(next(java_id))
print(next(python_id))
print(next(java_id))
print(next(java_id))
print(next(python_id))
# f'{提供数据的表达式: 参数}'
# :字符>长度
#
# name = '张三'
# result = f'姓名:{name:x^5}'
# print(result)
4.生成器创建数据的原理(了解)
每次获取生成器的数据的时候,就会去执行创建这个生成器的函数体,但是每次执行都只会执行到yield就停下来。
def func2():
print('========')
yield 100
print('++++++++')
yield 200
print('!!!!!!!!')
yield 300
gen4 = func2()
print('1.:', next(gen4))
print('hello world!')
print('-------------------------华丽的分割线---------------------')
print('2.:', next(gen4))
print('-------------------华丽的分割线-------------------------')
result = map(lambda item: item*2, 'abc')
print(result)
print(next(result))
print(next(result))
print(list(result))
03装饰器
1. 什么是装饰器 - 给已经定义好的函数添加功能的工具
装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数。
2. 给函数添加功能
# 解决方案1: 直接修改原函数
# 练习:给函数添加功能,统计函数的执行时间
def hello():
start = time.time()
print('hello world!')
end = time.time()
print(f'总时间:{end - start}')
def factorial(n):
start = time.time()
s = 1
for x in range(1, n+1):
s *= x
print(s)
end = time.time()
print(f'总时间:{end - start}')
factorial(10)
# 解决方案二:
def total_time(fn, *args, **kwargs):
start = time.time()
fn(*args, **kwargs)
end = time.time()
print(f'总时间:{end - start}')
total_time(hello)
total_time(factorial, 10)
# 解决方案三:
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):
s = 1
for x in range(1, n+1):
s *= x
print(s)
hello()
factorial(6)
04 无参装饰器语法
"""
语法:
def 装饰器名(原函数):
def 添加完功能的新函数(*args, **kwargs):
调用原函数
添加新功能
return 添加完功能的新函数
语法细化:
def 装饰器名(f):
def new_f(*arg, **kwargs):
result = f(*arg, **kwargs)
新增功能
return result
return new_f
装饰器名 - 根据新增的功能来命名
"""
# 练习1:写一个装饰器,在函数调用之前打印 '千锋教育欢迎你!'
def add_tag(f):
# f = hello
def new_f(*args, **kwargs):
print('千锋教育欢迎你!')
result = f(*args, **kwargs)
return result
return new_f
@add_tag # hello = add_tag(hello)
def hello():
print('hello world!')
@add_tag # sum2 = add_tag(sum2)
def sum2(num1, num2):
return num1 + num2
hello()
print('和:', sum2(10, 89))
# 练习2: 写一个装饰器在函数调用结束的时候打印'=====end====='
def add_end(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
print('=====end=====')
return result
return new_f
# @add_end
# def sum3(num1, num2):
# return num1 + num2
#
#
# s = sum3(2, 34)
# print(s)
# 练习3:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍。 3 -> 300; 'abc' -> 'abc'; 1.23 -> 123
def magnify(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return result * 100
return result
return new_f
@magnify
def sum3(num1, num2):
return num1 + num2
print(sum3(20, 4))
05有参装饰器
"""
有参装饰器语法细化:
def 装饰器名称(s列表):
def 无参装饰器(f):
def new_f(*arg, **kwargs):
result = f(*arg, **kwargs)
新增功能
return result
return new_f
return 无参装饰器
参数列表 - 看实现装饰器新增功能需不需要额外的数据需要几个
"""
# 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍数。
def magnify(n):
def temp(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return result * n
return result
return new_f
return temp
@magnify(5)
def sum3(num1, num2):
return num1 + num2
print(sum3(100, 200))
# 练习2:写一个装饰器,用法如下
# 没有装饰器返回值如果是: 100 @tag(p) -> '<p>100</p>'
# 没有装饰器返回值如果是: 'abc' @tag(a) -> <a>abc</a>
def change(p1):
def change1(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if p1 == 100:
return f'<p>{p1}</p>'
elif p1 == 'abc':
return f'<a>{p1}</a>'
return p1
return new_f
return change1
@change(100)
def sum1():
return
print(sum1())
# 练习3: 写一个装饰器(针对返回值是数字的函数),用法如下
# 12 -> @operation('+', 100) -> 112
# 12 -> @operation('-', 20) -> -8
# 12 -> @operation('*', 3) -> 36
# 12 -> @operation('/', 3) -> 4.0
def operation(operator, n):
def temp(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return eval(f'{result}{operator}{n}')
return result
return new_f
return temp
@operation('/', 3)
def nums(nums1):
return nums1
print(nums(12))