Day10 of learning python--函数初阶与闭包

1.为什么要使用函数

  因为函数的可读性强,而且复用性强

2.函数的定义格式

  def 函数名():

    函数体

    return 返回值

1 def func():
2     a = 2
3     return a  #可有可不有
4 b = func()   #函数的调用
5 print(b)

 注意:所有的函数,只定义不调用就一定不执行,先定义后调用,并且只有调用了函数,才会执行函数体的d代码。

3.默认参数的陷阱

1 def qqxing(l=[])  # 默认参数相当于在函数外面定义了一个变量
2     l.append(1)
3     print(l)
4 
5 qqxing()   #[1]
6 qqxing()   #[1,1]
7 qqxing()   #[1,1,1]
8 # 如果默认参数的值是一个可变的数据类型
9 # 那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源

 

 4.命名空间

全局命名空间--我们写的代码但不是函数中的代码,是在程序从上到下被执行的过程中依次加载进内存的,放置了我们设置的所有变量名和函数名

局部命名空间--就是函数内部定义的名字,当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了

内置命名空间--python解释器,就是python解释器一启动就可以使用的名字(print,input,list,tuple)存储在内置命名空间中,内置的名字在启动解释器的时候就被加载在内存里

在局部:可以使用全局、内置命名空间中的名字

在全局:可以使用内置命名空间中的名字,不能使用局部的名字

在内置:不能使用局部和全局的名字

 注意:当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字,在正常的情况下,直接使用内置的名字,当我自己有得时候,我就不找我得上级要,如果没有,就找上一级要了,继续找,没有就报错。

 1 a = 1
 2 b = 2
 3 def wa():
 4     x = 'aaa'
 5     b = 'bbb'
 6     print(locals())
 7 
 8 wa()
 9 print(globals())
10 print(locals()) # 本地的
11 # globals永远打印全局的名字
12 # locals输出什么根据local所在的位置
输出:

{'x': 'aaa', 'b': 'bbb'}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002763BAB6390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/testfile/test1/Day10/04 测试.py', '__cached__': None, 'a': 1, 'b': 2, 'wa': <function wa at 0x000002763BA6D268>}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002763BAB6390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/testfile/test1/Day10/04 测试.py', '__cached__': None, 'a': 1, 'b': 2, 'wa': <function wa at 0x000002763BA6D268>}

 

 5.函数的嵌套

在函数内部定义函数

1 def the_max(a,b,c):  # 函数的嵌套调用
2     z = max(a,b)
3     return max(z,c)
4 
5 def max(a,b):
6     return a if a > b else b
7 
8 print(the_max(1,2,3))

 

 函数的嵌套定义,内部函数可以使用外部函数的定义

 1 def  outer():
 2     a = 1
 3     def inner():
 4         nonlocal a #声明了一个上面第一层上层局部变量
 5         a += 1   # 不可变数据类型的修改
 6         print(a)
 7         print('inner')
 8     inner()
 9 outer()
10 
11 # nonlocal 只能用于局部变量 找上层中离当前最近一层的局部变量
12 # 声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量
13 # 对全局无效,也只是对最近的一层有效
 1 a = 1
 2 def outer():
 3     a = 1
 4     def inner():
 5         b = 2
 6         def inner2():
 7             nonlocal a
 8             a += 1
 9         inner2()
10         print('###a###:',a)
11     inner()
12     print('***a***:',a)
13 
14 outer()
15 print('全局:',a)
结果:

###a###: 2
***a***: 2
全局: 1

 

 6.函数名的使用

func --> 指向函数得内存地址
函数名() -->函数调用
函数得内存地址() -> 函数调用

函数名:第一类对象
1.可在运行期创建
2.可用作为函数参数或返回值
3.可存入变量的实体

 

 

 1 def func():
 2     print(123)
 3 
 4 # func 函数名就是内存地址
 5 func2 = func
 6 func2()
 7 
 8 l = [func,func2] #函数名可以作为容器类型的元素
 9 print(l)
10 for i in l:
11     i()
12 
13 def wa(f):
14     f()
15     return f # 函数可以作为函数的返回值
16 
17 qqxing = wa(func2) #函数名可以作为函数的参数
18 print(qqxing)

 

 7.闭包

使用的意义是,不用重复的为变量创建空间,节省内存。

1 #闭包:嵌套函数,内部函数调用外部函数的变量
2 def outer():
3     a = 1
4     def inner():
5         print(a)
6     print(inner.__closure__)
7 outer()
结果:(<cell at 0x0000020A92B6D948: int object at 0x00007FF92D75D420>,),有个cell自得就是闭包

 

 1 # import urllib # 模块
 2 from urllib.request import urlopen
 3 # ret = urlopen('http://www.xiaohua100.cn/index.html').read()
 4 # print(ret)
 5 def get_url():
 6     url = 'http://www.xiaohua100.cn/index.html'
 7     def get():
 8         ret = urlopen(url).read()
 9         print(ret)
10     return get
11 
12 get_func = get_url()
13 get_func()

 

8.作用域

全局作用域 -- 作用在全局 -- 内置和全局空间中得名字都属于全局作用域 --globals()
      对于不可变数据类型 在局部可查看全局作用域中得变量,但是不能修改
      如果想要修改,需要在函数体中一开始添加global声明
      如果在一个局部内(函数)内声明了一个global变量,那么这个变量在局部得所有操作将对全局的变量有效
局部作用域 -- 作用在局部 --函数(局部名字空间中得名字属于局部作用域) --locals()

 

posted on 2018-09-21 21:03  smile大豆芽  阅读(152)  评论(0)    收藏  举报