1基础知识
主要是结合菜鸟教程对一些重要或者模糊的知识点进行记录,另外敲写一遍基础代码
18
# flist = []
# for i in range(3):
# def foo(x):
# print (x + i)
# flist.append(foo)
# for f in flist:
# foo(2)
# foo(2)
这段代码中第一个for中的foo在for i in range(3):中不执行,只有在 for f in flist:中调用的时候才执行,其中的i值是在定义的时候赋值的其定义时是在for已完成后才调用时引用的i,这个时候的i已经是2了。这个引用的意思就是之前是指向i的值的保存地址并不去寻址,只有在调用函数时才会去寻址
注意此处将foo定义在for外,无法直接引入i,需要将i放入数列中再取,代码复杂了。但我觉得这个方法会比较稳妥一些
另外也可以直接在函数内执行函数。
直接压入函数进入flist列中,列表中的局部变量i在压入时是i的指向地址,该地址在循环时不变,它所指向的值是变化的,在最后函数调用时,才会取值,这时i已经不是存入时所指向的值了,变了
x=3
def f():
print(x)
涉及到的几个重要点
https://jingyan.baidu.com/article/574c52196b604c6c8d9dc133.html
19 对16的补充
闭包中的内函数可以引用外函数的局部变量,这涉及到python的变量域问题,但在想要修改的时候就只能使用globle和nolacale的变量声明,或者是可修改的变量如列表,不然会报错因为python在解析到赋值语句时会先解析等号右边的计算部分,此时会认为盖变量为内函数局部变量,在内函数中没有,所以便会报错。
这个情况在普通函数中想要更改外部变量也是会报错,逻辑也是在解析时会将等号右边的计算式中的变量当做局部变量
这个博文的代码会比较好的说明这个问题
https://www.cnblogs.com/Lin-Yi/p/7305364.html
20变量掩盖和修改规则
python是一行一行的解释的,块是先读完再解释,同时存在先定义在使用的规则
该代码违反了先定义后使用
def b():
print(v)
v = 1
b()
这个代码也是违反了先定义后使用
print(x)
x = 1
这个代码违反了先定义后使用,注意与第一个代码区别,区别在该代码的print(x)是x为局部变量有值2,但是按照块读完def的函数时,赋值局部变量x后审查规则时与先定义规则冲突才报错的
x = 1
def ss():
print (x)
x = 2
NameError: name ‘x’ is not defined
变量掩盖的意思是掩藏了而非修改,同名的局部变量会在函数中掩盖全局变量,函数执行完后局部变量释放,不在函数外掩盖全局变量
21装饰器也是一种闭包,他将函数作为参数传递到其他函数,然后返回一个内部函数,注意是直接使用函数名进行赋值和return,不添加(),函数不添加()时是一个函数,在需要得到结果时直接加入()在后面就能时函数执行
而@的结构表示@后的函数时@下一行函数的使用函数,这样在直接使用下一行函数时会先将该函数赋值给@后的函数,实现装饰器效果。
22装饰器里面有一个@wraps,接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。使用这个装饰器是因为我们在使用装饰器后直接输入被装饰的函数,我们对这个函数的专有属性name和help等进行取值会发现我们取的是装饰器里面的函数的,因为装饰器给我们返回的是闭包函数,那么我们要想取得原有的这些属性就需要用@wraps,他的装饰器作用是修改返回函数的这些参数为原函数的,即重新定义。注意from functools import wraps 并将装饰其中返回函数进行装饰,即修改他的参数
https://www.cnblogs.com/myd7349/p/how_to_use_wraps_of_functools.html
23装饰器中的参数传递使用的和函数定义一样,大多为*tup,**dict
直接的数值传入元组,使用tup【1】取,=的赋值形式传入字典,使用dirt【“you”】来取值
https://www.bilibili.com/video/av25698102?from=search&seid=7770645137069963120
24 我在编写迭代器运行时报错
maximum recursion depth exceeded while calling a Python object
并且修饰部分迭代输出
这个错是指迭代深度,默认是1000,可以将其修改
但这里是代码有误,传递函数在修饰器里面使用的不是参数李德兴市,而是函数原名,这就造成了迭代
23构造器是负责变量初始化的函数,在类中是init这个专有方法
生成器使用了yeild函数的函数
迭代器 是使用了iter和next函数的函数部分