day-4 名称空间 作用域 函数嵌套 函数名 闭包 装饰器

1.1名称空间的分类

名称空间的定义:存放名字与值的关系的空间起了一个名字

 

名称空间分为三种:

  全局命名空间

  局部命名空间

      内置命名空间

A.全局名称空间

代码在运行伊始,创建的存储“变量名与值的关系”的空间

B.局部名称空间

在函数的运行中开辟的临时的空间

 

C.内置名称空间

存放了python解释器为我们提供的名input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

 

1.2名称空间的一些规则

当程序运行时,代码从上至下一次执行,会将变量与值的关系存储在一个空间中,这个空间叫做名称空间,命名空间,全局名称空间。

当程序遇到函数时,他会将函数名存在内存中,函数体莫不关心。

当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),函数外面访问不到临时空间的内容,随着函数的执行完毕,临时名称空间会释放掉,向这个临时开辟的空间叫临时名名称空间,也叫局部名称空间。

1.3作用域

作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

1.3.1全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

1.3.2局部作用域:局部名称空间,只能在局部范围内生效

1.4加载顺序

内置命名空间(程序运行前加载,也就是解释器运行的时候)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:函数调用时才加载)

1.5取值范围

在局部调用:局部命名空间->全局命名空间->内置命名空间

在全局调用:全局命名空间->内置命名空间

综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。

2.1内置函数 globals() locals()

   globals()返回字典,字典里面的内容是全局作用域

   locals()返回字典,当前位置的所有变量

2.1.1全局范围运行globals() locals()

name='alex'

age=1000

def func1():

    name1='oldboys'

    age=10

    # print(locals())

func1()

print(globals())

print(locals())

#此时打印的内容是一样的,其实都是全局的变量

# '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EBA3C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/d22-01/day-4/练习.py', '__cached__': None, 'name': 'alex', 'age': 1000, 'func1': <function func1 at 0x0000000001E13E18>}

2.1.1局部范围运行locals()

name='alex'

age=1000

def func1():

    name1='oldboys'

    age=10

print(locals())

# {'age': 10, 'name1': 'oldboys'}

func1()

print(globals())

# '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EBA3C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/d22-01/day-4/练习.py', '__cached__': None, 'name': 'alex', 'age': 1000, 'func1': <function func1 at 0x0000000001E13E18>}

3.1关键字global and nonlocal

3.1.2

3.1.2.1 global:

 1,声明一个全局变量。

 2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字,布尔值)。

  3,对可变数据类型(list,dict,set)可以直接引用不用通过global。

3.1.2.2 对于第2点的举例:

A.可引用并修改全局变量

count = 1

def func1():

    global count

    count=count+1

    print(count)

func1()#count为2

B.在局部声明全局变量

def func1():

    global name

     name='alex'

func1()

print(name)#alex

3.1.2.3 对于第3点的举例:

l1=[1,2,3]

def func1():

    l1.append(4)

    print(l1)

func1()#[1, 2, 3, 4]

l1.append(5)

print(l1)# [1, 2, 3, 4, 5]

3.1.1

nonlocal:  1,不能修改全局变量。

2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

def add_b():

    b = 42

    def do_global():

        b = 10

        print(b)#10

        def dd_nonlocal():

            nonlocal b

            b = b + 20

            print(b)#30

        dd_nonlocal()

        print(b)#30

    do_global()

    print(b)#42

add_b()

运行结果:

10

30

30

42

3.2取值的定义及规则

取值:引用而不是改变

取值是从小到大LEGB,想改变上层空间的变量,要用到global或者nonlocal

4.函数的嵌套和作用域

4.1函数的嵌套一:在一个函数调用全局定义的函数

def max2(x,y):

    m  = x if x>y else y

    return m

def max4(a,b,c,d):

    res1 = max2(a,b)

    res2 = max2(res1,c)

    res3 = max2(res2,d)

    return res3

result=max4(23,-7,31,11)

print(result)#31

4.2函数的嵌套二:在函数里定义函数并调用函数

1.

def f1():

    print("in f1")

    def f2():

        print("in f2")

    f2()

f1()

#输出结果

in f1

in f2

2.

def f1():

    def f2():

        def f3():

            print("in f3")

        print("in f2")

        f3()

    print("in f1")

    f2()

f1()

#输出的结果

in f1

in f2

in f3

4.3函数的作用域

小范围作用域可以使用大范围的变量,但是反之不行,他是单向的。

4.3.1例子1:

def f1():

    a = 1

    def f2():

        def f3():

            print(a)

        f3()

    f2()

f1()

#输出结果为1

例子2:

def f1():

    a = 1

    def f2():

        a = 2

        print('a in f2:',a)

    f2()

    print('a in f1:',a)

f1()

#输出结果:

a in f2: 2

a in f1: 1

5.函数名

5.1可被引用

def func():

    print('in func')

f = func

print(f)# <function func at 0x00000000003B3E18>

5.2可作为容器元素

def func1():

    print(111)

def func2():

    print(222)

def func3():

    print(333)

l1=[func1,func2,func3]

for i in l1:

i()

5.3函数名可作为参数传递

def func1():

    print(111)

def func2(x):

    x()

    print(222)

func2(func1)

5.4函数名可以作为返回值

def func1():

    print(111)

def func2():

    print(222)

    return func1

ret=func2()()

5.5函数名可作为变量赋值

def func1():

    print(111)

    return 111

f1=func1

f2=f1

f3=f2

f3()

print(f3)

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

1.可在运行期创建

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

3.可存入变量的实体。

6.闭包函数

内存函数对外层函数非全局变量的引用。

作用:用于装饰器和网络爬虫

6.1例子

def func():

    name = 'eva'

    def inner():

        print(name)

    return inner

f = func()

f()#输出eva

6.2判断闭包函数的方法__closure__

#输出的__closure__有cell元素 :是闭包函数

def func():

    name = 'eva'

    def inner():

        print(name)

    print(inner.__closure__)

    return inner

f = func()

f()

#(<cell at 0x00000000027B65B8: str object at 0x00000000028382D0>,)

#eva

#输出的__closure__为None :不是闭包函数

name = 'egon'

def func2():

    def inner():

        print(name)

    print(inner.__closure__)

    return inner

f2 = func2()

f2()

#None

#egon

7.装饰器

装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

装饰器 本质就是闭包

7.1 装饰器的固定格式

def wrapper (func):

    def inner(*args,**kwargs):

        '''执行函数之前要做的'''

        re = func(*args,**kwargs)

        '''执行函数之后要做的'''

        return re

return inner

7.2装饰器的应用

装饰器的应用在被装饰的函数前面

@wrapper

def essay():

    print ('欢迎用户{}进入文章页面'.format (status_dict['username']))

猜你喜欢

转载自www.cnblogs.com/junyingwang/p/9120322.html