python全栈-Day 10

一、命名空间和作用域

1、内置命名空间——对应Python解释器

  • Python解释器一启动就可以使用的名字存储在内置命名空间中,比如print、len、list、tuple、dict==
  • 内置的名字在启动解释器的时候被加载进内存里

2、全局命名空间——对应 非函数的自定义代码

  • 放置了我们设置的所有变量名和函数名(所有名字)
  • 在程序从上到下被执行的过程中,一次加载进内存的

3、局部命名空间——对应 自定义函数

  • 是函数内部定义的变量名和函数名
  • 当调用函数的时候才会产生这个名称空间,随着函数执行的结束,该命名空间被回收

4、命名空间的其他内容

  • 在局部,可以使用 当前局部、全局、内置命名空间中的名字。局部命名空间根据函数个数可能有多个,其之间是隔离的,不能相互调用
  • 在全局,可以使用 全局、内置命名空间的名字,但是不能使用局部命名空间的名字
  • 在内置,不可以使用 局部、全部命名空间的名字
  • 以上符合 依赖倒置原则:上层模块应该依赖底层模块,底层模块不能依赖上层模块
  • 在正常情况下使用内置的名字,会使用内置的函数或变量;在全局定义了和内置命名空间中 同名的名字时,会使用全局的函数或变量
  • ——即,如果自己有就用自己的,如果自己没有就找底层的
    print(max([1,2,3]))
    
    def max():    #重新定义了max的函数
        print('in max func')
    
    max()    #in max func----函数内存地址(),指的是内存调用
    print(max())    #None
    print(max)  #<function max at 0x101eb48c8>----函数名的值其实是  函数的内存地址

5、作用域

  • 全局作用域:作用在全局,内置和全局名字空间中的名字都属于全部作用域
  • 局部作用域:作用在局部,函数-局部名字空间中的名字属于局部作用域
  • 对于不可变数据类型,在局部可以查看全局作用域中的变量,但是不能直接修改,如果想要修改,需要在该函数中添加一个声明
  1. global:声明一个全局变量,作用域 是全局和局部的命名空间----不建议使用,不安全!!!建议使用形参、实参、返回值来修改
  2. nonlocal:声明一个上层局部变量,作用域是 最近一层的可找到对应名字的命名空间
  • a = 1
    def func():
        #a += 2    #报错
        a = 2
        print(a)    #重新定义了一个局部变量a = 2
    
    func()
    print(a)  #1,全局变量1没有改变
    
    a = 1
    def func():
        global a
        a = 2
        print(a)  #2
    
    func()
    print(a)  #2
  • 两个方法:globals、locals----用的比较少
    a = 1
    b = 2
    def func():
        x = 'aaa'
        y = 'bbb'
        print(locals())  #返回局部作用域中的所有名字及其值
        print(globals())  #返回全局的名字
    func()

二、三元运算符???视频丢失

1、适合用三元运算的场景:

  • 必须要有结果
  • 必须要有if和else
  • 只能是简单的情况

2、三元运算的格式:  变量 = 条件返回True的结果 if 条件 else 条件返回False的结果

def max(a,b):
    return a if a>b else b

print(max(1,2)) 

三、函数的嵌套和作用域链

1、一个函数嵌套调用的示例

def max(a,b):
    return a if a>b else b

def the_max(x,y,z):
    return max(x,max(y,z))

print(the_max(12,3,4))

2、函数嵌套的定义:

#一个错误的函数嵌套定义的流程
def outer():
    def inner():
        print('inner')

outer()  #调用outer函数,outer函数体只定义了inner,没有执行inner内部的函数体

#一个正确的函数嵌套定义的流程
def outer():
    a = 1
    def inner():
        print(a)
        print('inner')
    inner()

outer()  #调用outer函数,outer函数体定义了inner,之后又执行了inner内部的函数体

3、作用域链:在内部函数使用变量的时候,是从小局部->大局部->全局->内置名字的过程,一级一级往上找,找到最近的一个就使用

def outer():
    a = 1
    def inner():
        a = 1
        def inner2():
            nonlocal a
            a = a + 1
            print(a,'inner2')
        inner2()
        print(a, 'inner')
    inner()
    print(a, 'outer')
outer()  #调用outer函数,outer函数体定义了inner,之后又执行了inner内部的函数体

'''返回结果:
2 inner2
2 inner
1 outer'''


def outer():
    a = 1
    def inner():
        #a = 1
        def inner2():
            nonlocal a
            a = a + 1
            print(a,'inner2')
        inner2()
        print(a, 'inner')
    inner()
    print(a, 'outer')
outer()  #调用outer函数,outer函数体定义了inner,之后又执行了inner内部的函数体

'''返回结果:
2 inner2
2 inner
2 outer'''

四、函数名的本质----名字

  • 函数名本质上是一个指向函数内存地址的变量名
  • 函数名可以赋值
    def func():
        print('func')
    
    func2 = func    #函数名可以赋值
    func2()
  • 函数名可以作为容器类型(list、tuple、dict)的元素
    def func():
        print('func')
    
    l = [func,func2]    #函数名可以作为容器类型(list、tuple、dict)的元素
    for i in l:
        i()
  • 函数名可以作为函数的参数和返回值
    def func():
        print('func')
    
    def wahaha(f):    #函数名可以作为函数的参数
        f()
        return f
    wahaha(func)
    f1 = wahaha(func)    #函数名可以作为函数的返回值
  • 以上,函数名属于一个第一类对象,符合以下3个条件的对象就是第一类对象
  1. 可在运行期内创建
  2. 可用作函数的参数和返回值
  3. 可存入变量的实体

五、闭包

1、闭包的定义:嵌套函数,且内部函数调用外部函数的变量,就是闭包

def outer():
    a = 1
    def inner():
        print(a)
    print(inner.__closure__)    #(<cell at 0x101def648: int object at 0x1009e0980>,)
outer()
print(outer.__closure__)    #None,返回结果没有cell at...,证明该函数不是闭包

2、常见的闭包应用形式

#一般情况下,闭包函数的调用必须通过调用外部函数来实现,会重复创建和删除,减少运行时间消耗
#使用闭包的好处在于,保护一个局部变量a不被回收,且可以随时可以通过inn的全部变量调用
def outer():
    a = 1
    def inner():
        print(a)
    return inner
inn = outer()
inn()    #将闭包函数的函数名作为返回值,并在全局使用一个变量接收,此时可以在外部调用该函数 

3、闭包的一个实际应用

#import urllib    #导入urllib模块
from urllib.request import urlopen

def get_url():
    url = 'https://www.baidu.com/'
    def get():
        ret = urlopen(url).read()
        print(ret)
    return get

get_gunc = get_url()
get_gunc()

 

posted @ 2018-08-01 20:49  TXBB哭哭  阅读(138)  评论(0编辑  收藏  举报