1,函数的命令空间(内置命名空间,全局命名空间,局部命名空间),内置大于全局大于局部
2,内置命名空间,就是Python解释器一启动就可以使用的名字,存储在内置命名空间中,内置的名字(print,input,list,tuple等等),启动解释器的时候加载到内存里面;
3,全局命令空间,是在程序从上到下被执行的过程中一次加载到内存的,放置了我们所有的变量名和函数名;
4,局部命名空间,就是函数内部定义的名字,当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个名称空间就又消失了
5,在局部,可以使用全局,内置空间中的名字;在全局,可以使用内置空间中的名字,但是不能用局部中中的名字;在内置空间,不能使用局部或者全局的名字
6,在正产改的情况下,直接使用内置的名字,当我在全局中定义了和内置名字空间中同名的名字时,我们会使用全局的名字
7,当我自己有的时候,我就不找上一级要了,当我自己没有的时候,就找上一级要,上一级也没有,再找上一级,都没有,就报错
8,函数名的本质是函数的内存地址,函数名加上括号,是函数的调用,函数的内存地址加上括号也是函数的调用,估计没人会这么用
9,作用域有两种:全局作用域(内置和全局命名空间中的名字术语全局作用域),局部作用域,作用在局部(函数,局部名字空间中的名字术语局部作用域)
10,对于不可变数据类型,在局部可以直接查看全局作用域中的变量,但是不能修改,如果想要修改,需要在程序一开始的时候添加global声明。
11,如果一个局部函数内声明了一个global的变量,那么这个变量在局部的所有操作,都是对全局变量的操作
12,locals和globals 查看全局和局部变量,加上global就不在是局部变量了,globals()永远打印全局变量,locals根据所在位置输出
a = 1 def func(): c =1 a = 2 # global a # a = 2 print(locals()) func() 运行结果: {'c': 1, 'a': 2} a = 1 def func(): c =1 # a = 2 global a a = 2 print(locals()) func() 运行结果: {'c': 1}
13,上一小节复习,所有的函数只定义不调用就一定不执行,先定义后调用,直接写函数名() 这样不接收返回值,返回值=函数名() 接收返回值 ,只写一个return是巍峨结束一个函数,返回一个值,结束了函数,且返回一个值
14,复习,形参来说,位置参数必须传,*args 可以接收零到多个按位置传入的参数,默认参数,可以不传,**kwargs:动态参数,可以接收任意多个按照关键字传递的参数。
15,复习,实参来说,调用的时候,按照位置传参数,按照关键字传参数,可以混用,但是位置必须在关键字之前,不能对一个参数重复赋值。
16,默认参数的陷阱问题,如果默认参数是一个可变的数据类型,那么每一次调用函数,的时候,如果不传值,就公用这个数据类型的资源
def func(li = []): li.append(1) print(li) func() func() func() func() func([]) # 这儿因为传入了新的参数列表,不共用,所有其他的使用默认参数的,都共用那一个列表 func() 运行结果: [1] [1, 1] [1, 1, 1] [1, 1, 1, 1] [1] [1, 1, 1, 1, 1]
17,对于字典也是一样的,因为key 不能重复,所以每次值是可以更新的,同样有陷阱
def func(k,dict1={}): dict1[k]='v' print(dict1.items()) func(1) func(3) func(4) func(5) func(6,{}) func(7) 运行结果: dict_items([(1, 'v')]) dict_items([(1, 'v'), (3, 'v')]) dict_items([(1, 'v'), (3, 'v'), (4, 'v')]) dict_items([(1, 'v'), (3, 'v'), (4, 'v'), (5, 'v')]) dict_items([(6, 'v')]) dict_items([(1, 'v'), (3, 'v'), (4, 'v'), (5, 'v'), (7, 'v')])
18,三元运算符
# 定义函数找出两个数中的最大值 def max_of_two(a,b): return a if a>b else b #定义函数,找出三个数中的最大值 def max_of_three(a,b,c): z = max_of_two(a,b) # 函数的嵌套调用 return max_of_two(z,c) print(max_of_three(3,4,5))
19,函数的嵌套定义
def outer(): def inner(): print("i am inner") outer() # 这样写并不会打印里面的那句话,因为只是定义了然,然后没有调用,就结束了
def outer(): def inner(): print("i am inner") inner() # 加上这句话才会打印的 outer() # 这样写并不会打印里面的那句话,因为只是定义了然,然后没有调用,就结束了
20,内部函数虽然不能直接修改外部函数的变量,但是可以看和使用
def outer(): a = 1 def inner1(): b = 2 print(a) print("i am inner") def inner2(): print(a,b) print("i am inner2") inner2() inner1() # 加上这句话才会打印的 outer() 运行结果: 1 i am inner 1 2 i am inner2
21,本空间有的变量,不会向上一层去找了就,申明了global的变量,只会对全局里面的变量进行操作
a =1 def outer(): a = 10 def inner1(): a = 100 # 本空间有的变量,不会向上去找了就 print(a) print("i am inner") def inner2(): global a # 不可变数据类型的修改,这样定义只是修改全局变量的a 并不会修改函数内的a a +=1 # 不可以这样修改 print(a) print("i am inner2") inner2() inner1() # 加上这句话才会打印的 outer() 运行结果: 100 i am inner 2 i am inner2
22,不可变数据类型的修改,如果想要修改上层函数内部的变量,而不是全局变量,可以用nonlocal,会一层层往上找,但是不会用全局空间里面的变量
nonlocal只应用于局部变量,找上层中离当前函数最近的一层的局部变量,声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量
对全局无效,对局部也只是对最近的有这个变量的一层有效。
a =1 def outer(): a = 10 def inner1(): a = 100 # 本空间有的变量,不会向上去找了就 print(a) print("i am inner1") def inner2(): nonlocal a a +=1 print(a) print("i am inner2") inner2() inner1() # 加上这句话才会打印的 outer() 运行结果: 100 i am inner1 101 i am inner2
a =1 def outer(): a = 10 def inner1(): # a = 100 # 本空间有的变量,不会向上去找了就 print(a) print("i am inner1") def inner2(): nonlocal a a +=1 print(a) print("i am inner2") inner2() inner1() # 加上这句话才会打印的 outer() 运行结果: 10 i am inner1 11 i am inner2
a =1 def outer(): # a = 10 #注释掉 def inner1(): # a = 100 # 注释掉 print(a) print("i am inner1") def inner2(): nonlocal a a +=1 print(a) print("i am inner2") inner2() inner1() # 加上这句话才会打印的 outer() 运行结果: File "/Users/guolixiao/PycharmProjects/lisa's_practise/boys/10.2.py", line 28 nonlocal a ^ SyntaxError: no binding for nonlocal 'a' found
23,后端语言有好多种,Python/java/C/C++/JAVA/PHP,每个语言占得分量差不多,前端语言有HTML/CSS/JS, 其中JS占据着举足轻重的地位。
24,函数名就是变量地址,函数名可以赋值,函数名可以作为容器类的元素
def func(): print("happy day") func2 = func # 注意不加括号才表示地址,加了括号表示调用 li = [func2,func] for i in li: print(i) i() # 其实就理解为普通变量用 运行结果: <function func at 0x10638e840> happy day <function func at 0x10638e840> happy day
25,函数名可以作为函数的参数
def func(): print("happy day") def wahaha(f): f() wahaha(func) 运行结果: happy day
26,函数名可以作为返回值
def func(): print("happy day") def wahaha(f): f() return f #函数名可以作为返回值 qqxing=wahaha(func) qqxing() 运行结果: happy day
27,函数名可以在运行是创建,可以当函数参数或者返回值,可以做容易类型的元素,可存入变量的实体
28,闭包:嵌套函数,内层函数使用外层函数的变量,不适用的话,就不是闭包
def outer(): a = 1 def inner(): print(a) # 这就是一个闭包
29,双下函数决定是否是闭包 __clousure__
def outer(): a = 1 def inner(): print(a) print(inner.__closure__) outer() 运行结果: (<cell at 0x10c269e88: int object at 0x10c01ec00>,) def outer(): a = 1 def inner(): print(1) #不再调用a print(inner.__closure__) outer() 运行结果: None
def outer(): a = 1 def inner(): print(a) print(inner.__closure__) outer() print(outer.__closure__) 运行结果: (<cell at 0x10edb6e88: int object at 0x10eb6ac00>,) None
30,如何在外部使用内部的函数?return
def outer(): a = 1 def inner(): print("inner") print(a) return inner inn = outer() inn() 运行结果: inner 1
31,写一个闭包的简单例子
from urllib.request import urlopen def get_url(): url = "http://www.xiaohuar.com/" def get(): ret=urlopen(url).read() print(ret) return get get_func = get_url() get_func() get_func() # 实现了一个简单的闭包