文章目录
1. 迭代器
1.1 什么是迭代器
(1)迭代器是容器;程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器
(2)特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;获取元素的时候每次只能获取最前面的那个元素,而且元素取一个就少一个
RIGHT Example:
i1 = iter('abc123')
print(i1) # <str_iterator object at 0x00000020195E4580>
i2 = iter([10, 23, 45])
print(i2) # <list_iterator object at 0x00000020195E4B50>
i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(i3) # <dict_keyiterator object at 0x0000002019624180>
WRONG Example:
i1 = iter('abc123')
print(len(i1)) # 报错,TypeError: object of type 'str_iterator' has no len()
1.2 查:获取元素
迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失
1.2.1 查单个
next(迭代器):获取迭代器中最前面的那个元素
RIGHT Example:
i1 = iter('abc123')
print(next(i1)) # 'a'
print(next(i1)) # 'b'
i2 = iter([10, 23, 45])
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)) # 报错,StopIteration,因为上一步类型转换把i3取完了
1.2.2 遍历
RIGHT Example:
i4 = iter('hello')
for x in i4:
print('x:', x)
# print(next(i4)) # 报错,StopIteration
2. 生成器
2.1 什么是生成器
生成器也是容器;其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法
生成器获取数据的方式和特点和迭代器一样
2.2 创建生成器
调用一个带有yield关键字的函数就可以得到一个生成器对象
RIGHT Example:
def func1():
print('+++')
print('===')
yield
return 100
result = func1()
print('result:', result)
# result: <generator object func1 at 0x0000004EC8F76B30>
2.3 控制生成器产生数据的个数和值
一个生成器产生的数据的个数和值由创建生成器调用的那个函数的函数体在执行时会遇到几次yield以及每次yield后面的值来决定
个数:由遇到的yield的次数决定
值:由yield后面的数据决定
RIGHT Example 1:
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
RIGHT Example 2 永动机:
def create2():
x = 0
while True:
yield x
x += 1
gen3 = create2()
for x in range(100):
print(next(gen3))
APPLICATION 写一个生成器,可以创建某个python班级的学生的学号,学号的范围是python0001~python1000:
def student_num(subject):
for x in range(1, 1001):
yield f'{subject}{x:0>4}'
python_num = student_num('python')
java_num = student_num('java')
print(next(python_num)) # python0001
print(next(python_num)) # python0002
print(next(java_num)) # java0001
print(next(java_num)) # java0002
# 注意:不能print(next(student_num))
2.4 生成器创建数据的原理
每次获取生成器的数据的时候,就会去执行创建这个生成器的函数体,但是每次执行都只会执行到yield就停下来
RIGHT Example :
def func2():
print('=======')
yield 100
print('+++++++')
yield 200
print('!!!!!!!')
yield 300
gen4 = func2()
print('1.:', next(gen4))
print('2.:', next(gen4))
print('3.:', next(gen4))
"""
=======
1.: 100
+++++++
2.: 200
!!!!!!!
3.: 300
"""
3. 装饰器
3.1 什么是装饰器
给已经定义好的函数添加功能的工具
装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数
3.2 给函数添加功能
RIGHT Example 给函数添加功能,统计函数的执行时间:
# 解决方案1:直接修改原函数
def hello():
start = time.time()
print('hello world!')
end = time.time()
print(f'总时间:{end - start}')
# 解决方案2:写一个新函数
def hello():
print('hello world!')
def total_time(fn, *args, **kwargs):
start = time.time()
fn(*args, **kwargs)
end = time.time()
print(f'总时间:{end - start}')
total_time(hello)
# 解决方案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!')
3.3 无参装饰器
语法:
def 装饰器名(原函数):
def 添加完功能的新函数(*args, **kwargs):
调用原函数
添加新功能
return 添加完功能的新函数
语法细化:
def 装饰器名(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
新增功能
return result
return new_f
装饰器名:根据新增的功能来命名
APPLICATION 写一个装饰器在函数调用结束的时候打印’= = = = = = end = = = = = =':
def end_line(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
print('======end======')
return result
return new_f
@end_line
def hello():
print('hello world!')
@end_line
def sum2(num1, num2):
return num1 + num2
hello()
print(f'和:{sum2(10, 89)}')
APPLICATION 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍:
def multiple(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return result * 100
return result
return new_f
@multiple
def hello():
print('hello world!')
@multiple
def sum2(num1, num2):
return num1 + num2
hello()
print(f'和:{sum2(10, 89)}')
3.4 有参装饰器
有参装饰器语法细化:
def 装饰器名称(参数列表):
def 无参装饰器(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
新增功能
return result
return new_f
return 无参装饰器
参数列表:看实现装饰器新增功能需不需要额外的数据需要几个
APPLICATION 1 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍数:
def multiple(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
@multiple(1000)
def sum2(num1, num2):
return num1 + num2
print(sum2(10, 20))
APPLICATION 2 写一个装饰器,用法如下:
# 没有装饰器返回值如果是:100 @tag(p) -> <p>100</p>
# 没有装饰器返回值如果是:'abc' @tag(a) -> <a>abc</a>
def tag(str1):
def temp(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
return f'<{str1}>{result}</{str1}>'
return new_f
return temp
@tag('b')
def sum2(num1, num2):
num1 + num2
print(sum2(10, 20))
APPLICATION 3 写一个装饰器,用法如下:
# 12 -> @operation('+', 100) -> 112
# 12 -> @operation('-', 20) -> -8
# 12 -> @operation('*', 3) -> 36
def operation(sign, num):
def temp(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return eval(sign.join([str(result), str(num)]))
return result
return new_f
return temp
@operation('+', 100)
def sum2(num1, num2):
return num1 + num2
print(sum2(10, 20))