装饰器本质就是一个实参高阶函数和返回值高阶函数。
装饰器是用来给函数添加功能的(在不修改原函数的基础上给函数添加功能)。
返回值高阶函数
def func1():
def func2():
return 'abc'
return func2
print(func1())
print(func1()())
def sum1(a, b):
time1 = time.time()
print(a+b)
time2 = time.time()
print('执行时间', time2 - time1)
sum1(1234885984556194516958458945, 451665189456566541564569645)
def factorial(n):
time1 = time.time()
sum1 = 1
for x in range(1, n+1):
sum1 *= x
print(sum1)
time2 = time.time()
print('执行时间:', time2 - time1)
factorial(123)
2.方法二:实参高阶函数
定义一个函数,功能是统计一个函数的执行时间
def count_execution_time(func, *args, **kwargs):
time1 = time.time()
func(*args, **kwargs)
time2 = time.time()
print('执行时间:', time2 - time1)
def func2():
print('hello,word')
count_execution_time(func2)
# 解包
def test (a, b, c):
print(f'a:{a}, b:{b}, c:{c}')
numes = [10, 20, 19]
test(*numes)
print(’=实参高阶函数改进’)
3. 方法三:实参高阶函数改进
def count_execution_time(func):
def test(*args, **kwargs):
time1 = time.time()
func(*args, **kwargs)
time2 = time.time()
print(f'执行时间:{time2-time1}')
return test
def 函数命1(func):
def test(*args, **kwargs):
func(*args, **kwargs)
添加新的功能
return test
说明:函数命1 - 装饰器对应的函数名,也就是装饰器的名字(根据需要添加的新功能命名)
func - func指向的是需要添加新功能的函数
test - 指向的是已经添加完新的功能的新函数
def print_end(func):
def test(*args, **kwargs):
func(*args, **kwargs)
print(f'end')
return test
@print_end
def func1():
print('=============')
func1()
def print_start(func):
def test(*args, **kwargs):
print('开始')
func(*args, **kwargs)
return test
@print_start
def func2():
print('=============')
func2()
def two_dici(func):
def test(*args, **kwargs):
result = func(*args, **kwargs)
if type(result) in [int, float]:
return float(f'{result:.2f}')
return result
return test
@two_dici
def sum3(a, b):
return a + b
print(sum3(1, 2))
如果在实现装饰器新增的功能的时候需要额外的数据,那么就可以使用有参的装饰器
def 装饰器名称(装饰器的参数列表):
def test1(func):
def test2(*args, **kwargs):
func(*args, **kwargs)
添加的新功能
return test2
return test1
def N_deci(n):
def test1(func):
def test2(*args, **kwargs):
result = func(*args, **kwargs)
if type(result) == float:
nums = str(result).split('.')
return float(f'{nums[0]}.{nums[-1][0:n]}')
return result
return test2
return test1
@N_deci(4)
def sum1(a, b):
return a + b
print(sum1(3.1415926, 10))
def N_xing(n):
def test1(func):
def test2(*arg, **kwargs):
result = func(*arg, **kwargs)
for i in range(n):
print('*', end='')
print()
return result
return test2
return test1
@N_xing(10)
def sum1(a, b):
return a + b
print(sum1(3, 10))
def change_num(str, num):
def test1(func):
def test2(*args, **kwargs):
result = func(*args, **kwargs)
if type(result) in [int, float]:
if str == '-':
result -= num
return result
if str == '+':
result += num
return result
return result
return test2
return test1
@change_num('+', 10)
def factorial(n=5):
sum1 = 1
for i in range(1, n + 1):
sum1 *= i
return sum1
print(factorial())
迭代器的特点
迭代器是一种特殊的容器:a.不能直接查看所有的元素(打印看不到任何元素;不能计算长度) b.如果要读取元素的值,必须将这个元素从迭代器中拿出来,并且取出来后就再也放不进去了,迭代器中就不再有这个元素了)
创建迭代器
① 将其他序列转换成迭代器:iter(序列)
② 创建生成器(生成器的本质就是迭代器)
iter1 = iter([10, 20, 30, 40])
print(iter1) #
# print(len(iter1)) # TypeError: object of type 'list_iterator' has no len()
iter2 = iter('adasd')
注意:不管以任何方式获取到了迭代器的元素,这个元素在迭代器中就不存在了
①. 获取单个元素
next(迭代器) - 获取迭代器中最前面的一个元素
print(next(iter2))
print(next(iter2))
②. 遍历
for x in 迭代器
iter3 = iter(['name', 'age', 'hello', 'word'])
for x in iter3:
print(x)
iter4 = iter(range(5))
next(iter4)
next(iter4)
for x in iter4:
print(x)
生成器的本质就是迭代器:
生成器其实是能够产生多个数据的容器,而不是真正同时保存多个数据的容器
调用带有yield关键字的函数就能得到一个生成器
调用普通话函数:a.执行函数体 b.获取函数返回值
def func1():
print('abc')
return 100
print(func1())
调用带有yield关键字的函数:a.不执行函数体 b.获取到的是生成器对象
def func2():
yield
print('ABC')
return 200
result = func2()
list(result)
① 一个生成器能生产多少数据? - 看执行生成器对应的函数,在函数结束的时候能够遇到几次yield,就能生产多少个数据。
② 生成器生产的数据是那些? - 看每次遇到yield,yield后面的数据是什么,产生的数据就是什么
def func3():
yield
print('======')
yield
print('+++++')
gen1 = func3()
print(gen1)
print(len(list(gen1)))
def func4(n):
yield
if n % 2:
yield
print('end')
gen2 = func4(4)
print(len(list(gen2)))
生成器生产的数据是那些?
def func5():
yield 10
yield 100
gen4 = func5()
print(list(gen4))
调用函数创建生成器对象的时候不会执行函数体:当获取生成器中的元素的时候才会执行函数体。
获取第一个元素的时候从函数开始执行,执行遇到第一个yield就会停下来,并且将yield后面的数据作为这次获取到的元素,
下一次获取元素的时候从上一次结束的位置接着往后执行函数体直到遇到下一个yield,并且将新的yield后面的数据作为新的元素,
以此类推,如果从上次结束的位置开始到函数结束都没遇到yield,那么这个生成器就不再创建数据了,如果是next操作,这个时候会报错
注意:每次调用函数的时候都在创建新的生成器对象
def func6():
print('第一个:')
yield 10
print('第二个:')
yield 100
print('第三个:')
yield 'abc'
gen5 = func6()
print(next(gen5))
print(next(gen5))
def func7(n):
for m in range(n):
yield m * 2
gen6 = func7(10)
print(next(gen6))
练习:写一个学号的生成器,能够产生stu0001~stu9999的学号
def stu_num():
for x in range(1, 100):
num = str(x).rjust(4, '0')
yield f'stu{num}'
gen7 = stu_num()
print(list(gen7))