Python基础10(函数命名空间及作用域)

函数进阶

  命名空间和作用域

  内置命名空间----python解释器

        就是python解释器一启动就可以使用的名字存储在内置命名空间中
        内置的名字在启动解释器的时候被加载进内存里

  全局命名空间---我们写的代码但不是函数中的代码

        是在程序从上到下被执行的过程中依次加载进内存的

        放置了我们设置的所有变量名和函数名

  局部命名空间-------函数

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

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

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

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

  ps注意

    1》在正常情况下,直接使用内置的名字

    2》当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字

    3》当我们有的时候,就不找我的上一级要了

    4》如果自己没有就找上一级要

1 def max(l):
2     print('in max func')
3 print(max([1,2,3]))

    5》多个函数应该拥有多个独立的局部名字空间,不相互共享

1 def func(s):  # func ---> 函数的内存地址
2     # 函数名()----->  函数的调用
3     # 函数的内存地址()----->   函数的调用
4     print('in max func')
5 print(func)

  作用域

   作用域两种

   全局作用域---作用在全局---内置和全局名字空间中的名字都属于全局作用域   --------globals()

   局部作用域---作用在局部---函数(局部名字空间中的名字属于局部作用域)  ---------locals() 

   ps:注意

   对于不可变数据类型,在局部可以查看全局作用域的变量,但不能直接修改,如果想要修改,需要在程序的一开始添加global声明

    如果在一个局部(函数)内声明一个global变量,那么这个变量在局部的所有操作将对全局的变量有效

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

函数的嵌套和作用域链

  函数的嵌套调用

1 def max2(x, y):
2     i = y if x < y else x
3     return i
4 def max1(a,b,c,d):
5     s1 = max2(a, b)  # 函数的嵌套调用
6     s2 = max2(c, s1)
7     s3 = max2(d, s2)
8     return s3
9 print(max(1,2,3,4))

  函数嵌套定义

1 def f1():  # 声明函数f1
2     print("in f1")
3     def f2():  # 声明函数f2
4         print("in f2")
5 
6     f2()  # 调用函数f2
7 f1()  # 调用函数f1

  内部函数可以使用外部函数的变量

 1 a = 1
 2 def outer():
 3     a = 1
 4     def inner():
 5         a = 2
 6         def inner2():
 7             nonlocal a  #声明了一个上面第一层局部变量
 8             a += 1   #不可变数据类型的修改
 9         inner2()
10         print('##a## : ', a)  # ##a## :  3
11     inner()
12     print('**a** : ',a)  # **a** :  1
13 
14 outer()
15 print('全局 :',a)  # 全局 : 1

  nonlocal 

    nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
    声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量     对全局无效     对局部 也只是对 最近的 一层 有影响
 1 a = 0
 2 def outer():
 3     a = 1
 4     def inner():
 5         a = 2
 6         def inner2():
 7             nonlocal a
 8             print(a)
 9         inner2()
10     inner()
11 outer()

  函数名的本质

  函数名本质上就是函数的内存地址

  1.可以被引用

1 def func():
2     print('in func')
3 f = func
4 print(f)

  2.可以被当作容器类型的元素

 1 def f1():
 2     print('f1')
 3 
 4 
 5 def f2():
 6     print('f2')
 7 
 8 
 9 def f3():
10     print('f3')
11 
12 l = [f1,f2,f3]
13 d = {'f1':f1,'f2':f2,'f3':f3}
14 #调用
15 l[0]()
16 d['f2']()

  3.可以当作函数的参数和返回值

    第一类对象(first-class object)指

    1.可在运行期创建

    2.可用作函数参数或返回值

   3.可存入变量的实体  

闭包

  闭包函数:

    内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
    函数内部定义的函数称为内部函数

 

  由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!

  我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

  是不是直接就把这个函数的名字返回就好了?

  这才是闭包函数最常用的用法

1 def func():
2     name = 'eva'
3     def inner():
4         print(name)
5     return inner
6 
7 f = func()
8 f()

  判断闭包函数的方法__closure__


 1 #输出的__closure__有cell元素 :是闭包函数
 2 def func():
 3     name = 'eva'
 4     def inner():
 5         print(name)
 6     print(inner.__closure__)
 7     return inner
 8 
 9 f = func()
10 f()
11 
12 #输出的__closure__为None :不是闭包函数
13 name = 'egon'
14 def func2():
15     def inner():
16         print(name)
17     print(inner.__closure__)
18     return inner
19 
20 f2 = func2()
21 f2()

  闭包函数获取网络应用

 1 from urllib.request import urlopen
 2 
 3 def index():
 4     url = "http://www.xiaohua100.cn/index.html"
 5     def get():
 6         return urlopen(url).read()
 7     return get
 8 
 9 xiaohua = index()
10 content = xiaohua()
11 print(content)
12 
13 闭包函数获取网络应用

 PS 默认函数陷阱问题

 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 # 如果默认参数的值是一个可变数据类型,
10 # 那么每一次调用函数的时候,
11 # 如果不传值就公用这个数据类型的资源

 

 
posted @ 2017-12-27 20:00  争-渡  阅读(137)  评论(0)    收藏  举报