【漫漫转码路】Python Day 13

一、命名空间

命名空间(Namespace):是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的,它的键就是变量名,它的值就是那些变量的值。
注意: 大部分命名空间是字典;

1、内置命名空间

python语言内置的名称,包括所有内置的函数等;
从解释器启动时创建,持续到解释器中止;

# 例如
import builtins
print(dir(builtins))  # 返回所有内置函数及异常名称等;

dir([object]):不带参数时,返回当前范围内的变量、方法和定义的类型列表;
带参数时,返回参数的属性、方法列表;

2、全局命名空间

包含模块中定义的名称,记录了模块的变量、函数、类、其它导入的模块等
在模块被读入时创建,持续到解释器退出;

3、局部命名空间

包含函数中定义的名称,记录了函数的变量、参数等
一个函数的局部命名空间在这个函数被调用时创建,持续到函数结束

注意: 任何函数都是先定义,再调用

4、globals()和locals()

globals():返回当前全局命名空间(字典)
locals():返回当前局部命名空间(字典)

# 例如
def outer():
    def inner():
        print(globals())
        print(locals())
        
    inner()
    print(globals())
    print(locals())

outer()
# 终端显示
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002C7ED5BEFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/shenlanclass/PythonFiles/day13/day1301.py', '__cached__': None, 'outer': <function outer at 0x000002C7ED4D71F0>}  #inner全局变量
{}  # inner局部变量
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002C7ED5BEFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/shenlanclass/PythonFiles/day13/day1301.py', '__cached__': None, 'outer': <function outer at 0x000002C7ED4D71F0>}  # outer全局变量
{'inner': <function outer.<locals>.inner at 0x000002C7ED74C430>}  # outer局部变量

可以发现,outer和inner的全局变量都是一样的,只有outer,那是因为inner是outer的嵌套函数,全局变量只考虑最外面的函数、变量、模块,类等等;
inner的局部变量是空字典,因为inner里面没有函数及变量
outer的局部变量有inner,是因为Inner是outer的嵌套函数
全局命名空间下,globals和locals返回的字典一致;

注意: 命名的查找空间顺序:局部命名空间→全局命名空间→内置命名空间

5、eval和exac

eval(expression[,globals[,locals]]):执行表达式,并返回执行结果,表达式只能是一行,
exec(object[,globals[,locals]]):执行表达式,无返回值,表达式可以是多行,
注意: 当globals和locals不传参数的时候,则按照默认顺序找参数,如果两者有指定的时候,只能在制定的空间查找,此操作不是inplace操作,

# 例如
eval('print(abs(-9))')  # eval可以将字符串形式的表达式运行
print('----------------')
print(eval('print(abs(-9))')) #eval有返回值,返回后面的表达式,但是print返回none,因此输出none
print('----------------')
print(eval('abs(-9)'))  # eval有返回值,对返回值输出
print('----------------')
def num1(a):
    a = 999
    def num2():
        a = 10
        b = 11
        print(eval('a + b', {'a': 3, 'b': 4}))  # 当eval上传globals参数时,只能从上传参数里面选数据
    num2()
a = 0
b = 1        
num1(a)
print('----------------')
def num1(a):
    a = 999
    def num2():
        a = 10
        b = 11
        print(eval('a + b', {'a': 3, 'b': 4} ,{'a': 5, 'b': 6}))  # # 当eval上传globals和locals参数时,只能从上传参数里面选数据
    num2()
a = 0
b = 1        
num1(a)
print('----------------')
# 终端显示
9
----------------
9
None
----------------
9
----------------
7
----------------
11
----------------

eval和exac的区别

# 例如
string1 = '''
a = 1
b = 2
print(a+b)
'''
string2 = '''
abs(-9)
'''
exec(string1)  # exec可以运行多行语句
print(exec(string2))  #exec无返回值
# 终端显示
3
None

二、作用域

python可以直接访问命名空间的作用区域;
作用域分类:(作用域范围依次增大)
局部作用域:(Local)
闭包函数外的函数中:(Enclosing)
全局作用域:(Global)
内建作用域:(Built-in)
如果在当前函数作用域中找不到对应名称,则会向上一级去找,直到最后,如果找不到会报错;
只有模块,函数,类才会引入新的作用域,意思是,在全局作用域中,自定义函数,就会引入局部作用域;

1、闭包函数外的函数中

闭包函数外的函数中需要满足三点要求:
1、需要是个嵌套函数;
2、外部函数的返回值是内部函数的引用/调用;
3、内部函数用到外部函数的变量(参数);

# 例如
def out1():
    a = 1  # 这部分就是闭包函数外的函数中
    b = 2  # 这部分就是闭包函数外的函数中
    def in1():
        a = 0
        c = 5
        c= a + b + d + e
        print(c)
    return in1()
d = 3
e = 6
out1()
# 终端显示
11

注意: 区分调用和引用

2 、global和nonlocal

如果在局部作用域中,是没有办法对外部作用域的变量进行重新赋值的,此时我们可以用global和nonlocal实现;
global:对后面的全局变量重新赋值
nonlocal:对后面的闭包函数外的函数中变量重新赋值

# 例如
def out1():
    a = 1
    b = 2
    d = 7
    def in1():
        # a = 0
        # b = 5
        global a
        nonlocal b
        a += 1
        c= a + b + d + e
        print(c)
    return in1()
a = 3
b = 6
e = 8
out1()
print(a)
# 终端显示
21  # a=1,b=2,d = 7,e = 8
4  # 在局部变量中更改了全局变量a

注意:

# 例如
def out1():
    a = 1
    def in1():
        a = a + b
        print(a)
    in1()
a = 0
b = 1
out1()
# 终端显示
UnboundLocalError: local variable 'a' referenced before assignment
(赋值前引用的局部变量“a”)
# 此时,in1()中,a = a + b语句,会认为两个a都是局部变量,不会认为一个是局部变量,一个是Enclosing变量,python检测到在局部变量中对a有定义,但是在执行a+b的时候,发现a还没有被定义,因为局部变量中有a,因此也不会调用Enclosing变量,此时陷入矛盾,就会报错,
解决方法,定义globalnonlocal
# 解决方案
def out1():
    a = 1
    def in1():
        # global a  #定义全局变量
        a = 0  # 在局部变量中定义a,两者都可以解决
        a = a + b
        print(a)
    in1()
a = 0
b = 1
out1()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值