美文网首页
py_15 名称空间 作用域 嵌套函数

py_15 名称空间 作用域 嵌套函数

作者: 阿登20 | 来源:发表于2020-08-12 15:34 被阅读0次
一 名称空间
    1.1 内建名称空间:内置函数名,1个
    1.2 全局名称空间:函数外部的变量 函数名 类名 导入的模块名。1个
    1.3 局部名称空间:函数内变量,多个
    `名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间`

    `查找顺序为:局部名称空间->全局名称空间->内置名称空间
二 作用域
    全局作用域与局部作用域
    作用域与名字查找的优先级
三 嵌套函数
    1、嵌套函数简单的理解可以看作是在函数的内部再定义函数,实现函数的“私有”。
    2、特点:
    <1> 函数内部可以再次定义函数。
    <2> `只有被调用时才会执行(外部函数被调用后,被嵌套函数调用才有效)`

一 名称空间

名称空间即存放名字与对象映射/绑定关系的地方。对于x=3,Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中,del x表示清除该绑定关系。

在程序执行期间最多会存在三种名称空间

1.1 内建名称空间:内置函数名,1个

伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,比如内建函数名

>>> max
<built-in function max>

>>> sorted
<built-in function sorted>

存活周期:python解释器启动--产生, 解释器关闭--灭亡

1.2 全局名称空间:函数外部的变量 函数名 类名 导入的模块名。1个

伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,如下名字

存活周期:python文件执行--产生, python文件运行完毕后--灭亡

import sys #模块名sys

x=1 #变量名x

if x == 1:
    y=2 #变量名y

def foo(x): #函数名foo
    y=1
    def bar():
        pass

Class Bar: #类名Bar
    pass

1.3 局部名称空间:函数内变量,多个

伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中

局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁

存活周期:调用函数--产生, 调用完毕--灭亡

def foo(x):
    y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中

1.4 加载顺序和查找顺序

名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间

查找顺序为:局部名称空间->全局名称空间->内置名称空间。``L-E-G-B E:闭包作用域

画图理解:

image.png

二 作用域

image.png

2.1 全局作用域与局部作用域

按照名字作用范围的不同可以将三个名称空间划分为两个区域:

  1. 全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用);
  2. 局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)。

2.2 作用域与名字查找的优先级

在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常

x=100 #全局作用域的名字x
def foo():
    x=300 #局部作用域的名字x
    print(x) #在局部找x
    print(globals())
    print(locals())
foo()#结果为300
print(globals())
print(locals())

提示:可以调用内建函数locals()和globals()来分别查看局部作用域和全局作用域的名字,查看的结果都是字典格式。在全局作用域查看到的locals()的结果等于globals()

Python支持函数的嵌套定义,在内嵌的函数内查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域

x=1
def outer():
    x=2
    def inner(): # 函数名inner属于outer这一层作用域的名字
        x=3
        print('inner x:%s' %x)

    inner()
    print('outer x:%s' %x)

outer() 
#结果为
inner x:3
outer x:2

在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,则需要用到global关键字

x=1
def foo():
    global x #声明x为全局名称空间的名字
    x=2
foo()
print(x) #结果为2

当实参的值为可变类型时,函数体内对该值的修改将直接反应到原值,

num_list=[1,2,3]
def foo(nums):
    nums.append(5)

foo(num_list)
print(num_list)
#结果为
[1, 2, 3, 5]

对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)

def  f1():
    x=2
    def f2():
        nonlocal x
        x=3
    f2() #调用f2(),修改f1作用域中名字x的值
    print(x) #在f1作用域查看x

f1()

#结果
3

nonlocal x会从当前函数的外层函数开始一层层去查找名字x,若是一直到最外层函数都找不到,则会抛出异常。

三 嵌套函数

1、嵌套函数简单的理解可以看作是在函数的内部再定义函数,实现函数的“私有”。

2、特点:

<1> 函数内部可以再次定义函数。

<2> 只有被调用时才会执行(外部函数被调用后,被嵌套函数调用才有效)

def func1():
    print('hello world!')
    def func2():
        print('everyone...')

func1() # 输出:hello world! ,此时func2未被调用并不执行

age = 21
def func1():
    age = 19
    print('func1输出:',age) # 输出:19
    def func2():
        print('func2输出:',age) # 输出:19
    return func2  # 返回函数名

val = func1()  # 调用func1并将返回值赋给变量val,val = func2
print(val)  # 输出:<function func1.<locals>.func2 at 0x000002CE667298C8>
val() # 等于调用func2,返回函数定义处执行
print('全局输出:',age)  # 输出:21
1 #!/usr/bin/env python3
 2 #-*- coding:utf-8 -*-
 3 
 4 #情形1
 5 name = 'cc'
 6 def func1():
 7     name = 'sc'
 8     print(name)
 9     def func2():
10         #name = 'df'
11         print(name)
12     func2()
13 func1() #输出:sc  df,当第10行被注释时,输出:sc  sc,
14         # 嵌套函数中的变量层层调用,当前函数中没有便向上一级函数查找
15 
16 #情形2
17 age = 21
18 def func1():
19     def func2():
20         print(age) #输出:18,当前函数中并没有定义(‘第二层局部变量’)age,向第一层找
21     age = 18 #与func2位于同一层,‘第一层局部变量’
22     func2()
23 print(func1(),age)  #输出:None ,21,此时,函数外输出的age只能是全局变量
24 
25 #情形3
26 age = 21
27 def func1():
28     def func2():
29         print(age)
30     func2()
31     #age = 18
32 func1() #当31行不被注释时,运行会报错,打印age时会混淆全局age和局部age;
33         #当31行被注释时,输出: 21,此时func2调用全局age
34 
35 #情形4
36 age = 21
37 def func1():
38     global age #声明全局变量
39     def func2():
40         print('func2中的:',age) #输出>>func2中的: 21, age此时引用的是36行的全局变量
41     func2()
42     age = 18 #由于已经声明age是全局变量,所以此处的重新赋值就是对全局修改
43 func1()
44 print('全局中的:',age)  #输出>>全局中的: 18, 变量age在函数func1中被修改
45 
46 #情形5
47 age = 21
48 def func1():
49     global age
50     def func2():
51         print('func2中的:',age) #输出>>func2中的: 18,  age此时引用的是47行的全局变量
52     age = 18  #由于已经声明age是全局变量,所以此处的重新赋值就是对全局修改
53     func2()
54 func1()
55 print('全局中的:',age) #输出>>全局中的: 18, 变量age在函数func1中被修改
'''    情形4和情形5的区别在于age变量的修改在程序中的执行顺序,在func2调用前还是在func2调用之后,如果是在func2调用前修改age,则func2中输出的则是修改后的;如果是在func2调用后修改age,则func2中输出的就是未修改时的全局变量age,所以两者func2函数中输出的age值不同,但最后的全局输出相同。'''

相关文章

  • py_15 名称空间 作用域 嵌套函数

    一 名称空间 名称空间即存放名字与对象映射/绑定关系的地方。对于x=3,Python会申请内存空间存放对象3,然后...

  • day14 装饰器

    Ⅰ 闭包函数 闭包函数=函数嵌套定义+函数对象+名称空间作用域 闭:指的是该函数是定义再一个函数内部的函数...

  • python函数知识大全

    阅读目录 一 函数知识体系 二 函数基础 三 函数对象、函数嵌套、名称空间与作用域、装饰器 四 迭代器、生成器、面...

  • day14-函数(3)装饰器

    一、闭包函数 闭包函数=函数嵌套定义+函数对象+名称空间与作用域 闭包函数 1、闭:指的是该函数是定义在一个函数内...

  • 变量声明、声明提前和作用域

    一. 作用域 分为全局作用域和函数作用域 函数作用域简言之就是:变量在声明他们的函数体以及这个函数体嵌套的任意函数...

  • Python namespace

    namespace 作用域 locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数...

  • 作用域及闭包(closure)

    作用域:1. 全局 作用域链:函数嵌套 闭包(Closure)函数嵌套,在内嵌函数中使用到外部函数的局部变量(即内...

  • less基础学习记录总结

    目录 变量 混合 带参数混合 嵌套规则 运算 Color函数 命名空间 作用域 Importing 变量 less...

  • Python正式课第六天

    一、函数作用域 1. 局部作用域 L:local,局部作用域,即函数中定义的变量; 2. 嵌套作用域 E:encl...

  • python-函数

    作用域 L local局部作用域 E enclosing嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作...

网友评论

      本文标题:py_15 名称空间 作用域 嵌套函数

      本文链接:https://www.haomeiwen.com/subject/rmtmdktx.html