迭代器是容器; 程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器。
特点:
打印迭代器无法查看所有的元素、也无法获取元素的个数;
获取元素的时候每次只能获取最前面的那个元素,而且元素取一个就少一个。
i1 = iter('abc123')
print(i1) #
# print(len(i1)) # 报错!
i2 = iter([10, 23, 45])
print(i2) #
i3 = iter({'a': 10, 'b': 20, 'c': 30})
print(i3) #
# 查 - 获取元素
# 迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失
"""
1)查单个: next(迭代器) - 获取迭代器中最前面的那个元素
2)遍历
"""
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)) # 报错! 取完以后就报错
# 遍历
i4 = iter('hello')
for x in i4:
print('x:', x)
生成器也是容器;
其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法。
生成器获取数据的方式和特点和迭代器一样。
创建生成器
调用一个带有yield关键字的函数就可以得到一个生成器对象
def func1():
print('++++')
print('====')
yield
return 100
gen1 = func1()
print('result:', gen1) # result:
控制生成器产生数据的个数和值
一个生成产生的数据的个数和值由创建生成器调用的那个函数的函数体在执行的时候会遇到几次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))
# 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)
print('------------------------------------华丽的分割线-----------------------------------')
# 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))
作用:给已经定义好的函数添加功能的工具
装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数。
给函数添加功能的几种解决方法:
直接修改原函数
# 练习:给函数添加功能,统计函数的执行时间
# 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)
语法:
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))
有参装饰器语法细化:
def 装饰器名称(参数列表):
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) -> '100
'
# 没有装饰器返回值如果是: 'abc' @tag(a) -> abc
def tag(arg):
def temp(fn):
def new_f(*args, **kwargs):
result = fn(*args, **kwargs)
return f'<{arg}>{result}{arg}>'
return new_f
return temp
@tag('p')
def func11(i):
return i
# 练习3: 写一个装饰器(针对返回值是数字的函数),用法如下
# 12 -> @operation('+', 100) -> 112
# 12 -> @operation('-', 20) -> -8
# 12 -> @operation('*', 3) -> 36
# 12 -> @operation('/', 3) -> 4.0
def operation(arg1, arg2):
def temp(fn):
def new_f(*args, **kwargs):
result = fn(*args, **kwargs)
if type(result) in (int, float):
return eval(str(result) + arg1 + str(arg2))
return result
return new_f
return temp
@operation('/',6)
def func12(i):
return i
print(func12(1.3))