python三大神器
迭代器
1.什么是迭代器(iter)
迭代器是容器;程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器。
特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;获取元素的时候每次只能获取最前面的那个元素而且元素取一个就会少一个
i1 = iter('abc123')
print(i1) # <str_iterator object at 0x00000203733254B0>
# print(len(i1)) # 报错
i2 = iter([1, 2, 3])
print(i2) # <list_iterator object at 0x00000197365954B0>
i3 = iter({'a': 10})
print(i3) # <dict_keyiterator object at 0x00000197365F2BB0>
2.查
迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失
查单个:next(迭代器) - 获取迭代器中最前面的那个元素
遍历
示例:
print(next(i1)) # a
print(next(i1)) # b
i4 = iter('')
# print(next(i4)) # StopIteration
print(list(i1)) # ['c', '1', '2', '3']
i5 = iter({'a': 1, 'b': 2})
print(list(i5)) # ['a', 'b']
# print(next(i5)) # 报错
生成器
1.什么是生成器
生成器也是容器,其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法
生成器获取数据的方式和特点和迭代器一样。
2.创建生成器
调用一个带有yield关键字的函数就可以得到一个生成器对象
示例:
def func1():
yield
print('+++')
print('===')
return 100
result = func1()
print(result) # <generator object func1 at 0x0000024C45B74200>
3.控制生成器产生数据的个数和值
一个生成器的数据和个数由创建生成器调用的那个函数的函数体在执行的时候会遇到几次yield以及每次yield后面的值来决定
示例:
def create1():
yield 100
yield 200
yield 300
gen2 = create1()
# print(list(gen2)) # [100, 200, 300]
print(next(gen2)) # 100
# def create2():
# x = 0
# while True:
# yield x
# x += 1
#
# gen3 = create2()
# while True:
# print(next(gen3))
# 练习:写一个生成器可以创建某个Python班级的学时的学号,学号的范围师:python0001-python1000
def stu_id():
str1 = 'python'
x = 0
while x <= 1000:
x += 1
yield str1 + f'{x:0>4}'
id = stu_id()
for i in range(1, 1001):
print(next(id))
4.生成器创建数据的原理
每次获取生成器数据的时候,就回去执行创建这个生成器的函数体,但是每次执行都只会执行到yield就停下来
示例:
def func2():
print('=======')
yield 100
print('+++')
yield 200
print('!!!!')
yield 300
gen4 = func2()
print(next(gen4))
print(next(gen4))
print(next(gen4))
装饰器
1.什么是装饰器 - 给已定义号的函数添加功能的工具
装饰器就是一个函数,这个函数既是实参高级函数,又是返回值高阶函数
2.给函数添加功能
示例:
import time
# 练习:给函数添加功能,统计函数执行的时间
def hello():
# start = time.time()
print('hello world')
# end = time.time()
# print(f'总时间:{end - start}')
hello()
def factorial(n):
# start = time.time()
s = 1
for x in range(1, n + 1):
s *= x
print(s)
# end = time.time()
# print(end - start)
factorial(10)
# 解决方案2:
def total_time(fn, *args, **kwargs):
start = time.time()
fn(*args, **kwargs)
end = time.time()
print(end - start)
total_time(hello)
total_time(factorial, 5)
# 解决方案3:
def func1(fn):
def new_fn(*args,**kwargs):
start = time.time()
result = fn(*args,**kwargs)
end = time.time()
print(end - start)
return result
return new_fn()
无参装饰器
语法:
def 装饰器名(原函数):
def 添加完功能的新函数(*args,**kwargs):
调用原函数
添加新功能
return 添加完功能的新函数
def 装饰器名(fn):
def new_fn(*args,**kwargs):
result = fn(*args,**kwargs)
新增功能
return result
return new_fn
装饰器名 - 根据新增的功能来命名
示例:
def add_tag(f):
def new_f(*args, **kwargs):
print('1111')
result = f(*args, **kwargs)
return result
return new_f
@add_tag
def hello():
print('hello world')
def sum2(num1, num2):
return num1 + num2
hello()
# 练习2:写一个装饰器在函数调用结束的时候打印'end'
def end_(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
print('end')
return result
return new_f
@end_
def hello():
print('hello,world')
hello()
# 练习3:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍。 3 -> 300; 'abc' -> 'abc'; 1.23 -> 123
def fanbei(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return result * 100
else:
return result
return new_f
@fanbei
def adddata(x):
return x
print(adddata(1)) # 100
print(adddata('1')) # 1
有参装饰器
有参装饰器语法细化:
def 装饰器名称(参数列表):
def 无参装饰器(f):
def new_f(*args,**kwargs):
result = f(*args,**kwargs)
添加新功能
return result
return new_f
return 无参装饰器
参数列表 - 看实现装饰器新增功能需不需要额外的数据,需要几个
示例:
# 写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍
def fanbei(n):
def fanbei1(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
if type(result) in (int, float):
return result * n
else:
return result
return new_f
return fanbei1
@fanbei(5)
def adddata(x):
return x
print(adddata(6))
# 练习:写一个装饰器,用法如下
# 没有装饰器返回值如果是100 @tag(p) -> <p>100</p>
# 没有装饰器返回值如果是'abc' @ tag(a) -><a>abc</a>
def add1(n):
def add(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
return f'<{n}>{result}</{n}>'
return new_f
return add
@add1('p')
def adddata1(x):
return x
print(adddata1('abc'))
print(adddata1(100))
# 练习3:写一个装饰器(针对返回值是数字的函数),用法如下
# 12 -> @operation('+',100) -> 112
# 12 -> @operation('-',20) -> -8
# 12 -> @operation('*', 3) -> 36
# 12 -> @operation('/', 3) -> 4.0
def calculate(x: str, nums: int):
def calculate1(f):
def new_f(*args, **kwargs):
result = f(*args, **kwargs)
return eval(str(result) + x + str(nums))
return new_f
return calculate1
@calculate('*', 10)
def adddata2(n):
return n
print(adddata2(10)) # 100
@calculate('-', 10)
def adddata3(n):
return n
print(adddata3(10)) # 0