有参装饰器
-
有参装饰器
应用场景:如果实现装饰器的功能的时候需要额外的数据,就需要有参装饰器
def 函数名(参数列表):
定义无参装饰器函数
return 无参装饰器函数名
函数名 - 创建装饰器的函数名
参数名 - 有多个参数看实现装饰器的功能额外需要多少个数据
def create_tag(name): def tag(f): def new_f(*args, **kwargs): result = f(*args, **kwargs) return f'<{name}>{result}</{name}>' return new_f return tag @create_tag('*') def func1(): return 'abc' print(func1())
-
练习:写个装饰器将原函数的返回值加上指定的数
def create_tag(num): def add_num(f): def new_f(*args, **kwargs): result = f(*args, **kwargs) if type(result) in (int, float, bool, complex): return result + num return result return new_f return add_num @create_tag(100) def func2(): return 123 print(func2())
迭代器
- 什么是迭代器(iter)
- 迭代器是容器型数据类型
- 迭代器无法直接获取所有的元素,只能一个一个的取(取指的是拿出来,而且只出不进);也无法通过len统计元素个数
- 创建迭代器的方法:a.将其他序列转换成迭代器 b.生成器
list1 = [1, 23, 41, 59]
i1 = iter(list1)
print(i1, type(i1)) # <list_iterator object at 0x0000012B37130E08> <class 'list_iterator'>
# print(len(i1)) - TypeError: object of type 'list_iterator' has no len()
-
获取元素
不管以什么样的方式获取到了迭代器中的某个元素,那么这个元素在迭代器中就不存在了
-
获取单个元素
next(迭代器)
-
遍历
for 变量 in 迭代器:
循环体
i2 = iter('hello') print(next(i2)) # h print(next(i2)) # e print(next(i2)) # l print(next(i2)) # l print(next(i2)) # o # print(next(i2)) - StopIteration
-
-
i3遍历结束后的时候,会变成空的迭代器
i3 = iter(range(5)) for x in i3: print(f'x:{x}') # print(next(i3)) - StopIteration print(list(i3)) # [] i4 = iter(range(0, 10, 2)) # i4转换成列表后会变成空的迭代器 print(list(i4)) # [0, 2, 4, 6, 8] # print(next(i4)) - StopIteration
生成器
-
什么是生成器(generator)
-
感性的认识
生成器是一种特殊的迭代器
生成器可以理解成生产数据的机器,在存储的时候保存的时候产生数据的算法而不是数据本身
-
理性的认识
调用带有yield关键字的函数就可以得到一个生成器
(如果一个函数中有yield,那么调用这个函数不会执行函数体,也不会获取返回值,函数调用表达式的值是一个生成器对象)
-
-
这么创建生成器
def func1(): yield return 100 result = func1() # result就是一个生成器 print(f'result:{result}')
-
生成器产生数据的能力怎么确定
- 能创建多少个数据?有哪些?
- 看执行完生成器对应的函数会遇到几次yield,那么这个生成器就可以创造多少个数据
- 每次遇到yield,yield后面的值是什么,对应创造的数据就是什么
def func2(): yield yield 10 yield 100 gen1 = func2() print(next(gen1)) # None print(next(gen1)) # 10 print(next(gen1)) # 100 # next(gen1) - StopIteration def func3(): for x in range(5): yield 10**x gen2 = func3() for x in gen2: print(f'x:{x}')
-
生成器产生数据的原理
生成器对应的函数在调用函数的时候不会执行函数体;获取生成器中的数据的时候才会执行函数体
每次获取数据的时候,都是从上一次结束的位置开始执行函数体,直到遇到yield就停下来,将yield后面的数据作为结果,返回并且记录结束位置
如果是next去取,执行的时候如果遇到函数结束都没有遇到yield就报错!
def func4(): print('======1======') yield 10 print('======2======') yield 100 print('======3======') yield 1000 print('======4=====') yield 10000 print('======end=====') gen3 = func4() print(f'第一次取:{next(gen3)}') print(f'第二次取:{next(gen3)}') for x in gen3: print(f'x:{x}')
-
练习:写一个生成器能够产生指定前缀指定长度的学号
前缀:py,长度4, py0001~py9999
def create_num(front:str, length:int): for num in range(1, 10**length): """ 方法一: n = length-len(str(num)) yield front + '0'*n + str(num) """ # 方法二: # yield front+str(num).zfill(length) # 方法三: yield f'{front}{num:0>{length}d}' gen4= create_num('py', 4)
模块
-
什么是模块
一个py文件就是一个模块
-
怎么在一个模块中使用另外一个模块的内容
注意:如果一个模块想要被其他的模块使用,那么这个模块在命名的时候必须符合标识符的要求
一个模块想要使用另一个模块中的内容,必须先导入:
-
import 模块名 - 能够使用模块中所有的全局变量:使用的时候通过’模块名.'的方式
-
from 模块名 import 变量名1, 变量名2, … - 能够使用模块中指定变量:变量直接使用
-
模块重命名:import 模块名 as 新模块名
-
变量重命名:from 模块名 import 变量 as 新变量名
-
导入所有变量:from 模块名 import *
第一种导入方式:import
import test print(test.test_a) test.test_func()
第二种导入方式:from…import
from test import test_a, test_func print(test_a) test_func()
第三种导入方式:重命名
import test as TS test = 'hello' print(test) TS.test_func() print(TS.test_a)
第四种导入方式:变量重命名
from test import x as test_x, test_func for x in range(10): print(f'x:{x}') print(test_x) test_func()
第五种导入方式:通配符 *
from test import * print(test_a) print(x) test_func()
导入模块的原理
-
原理
当代码执行到导入模块的时候,系统会自动将被导入的模块中的代码全部执行一遍
解决方案:
if __name__ == '__main__':
这个if语句中的代码在被别的模块导入的时候不会执行,if语句外面的会被执行,如果直接运行当前模块,模块这个if中的代码会被执行