Python : locals 和globals 以及反射(自省)

来源:互联网 发布:织梦qq在线客服插件 编辑:程序博客网 时间:2024/06/05 19:25


python的两个内置函数,locals 和 globals,用于以一种基于字典的方式访问局部变量和全局变量,

python的变量记录在一个字典里,key是变量名,内容就是变量的值。这个字典称之为名字空间。

名字空间可以像普通的字典一样被访问。

如:在函数中,每个函数都有自己的名字空间,存储这函数的局部变量,参数等,

每个模块有自己的名字空间,叫全局名字空间,内含模块的变量,包括函数,类,导入的 模块,模块级的变量和常量,

另外还有内置的模块空间,可以被任何模块访问,存储着 build-in 函数和异常,

当引用一个变量时,按照  局部 ---  全局  ---   内置   的顺序来查找。如果找不到,抛出 NameError : name ‘x’  is  not defined。

python2.2之后,在一个嵌套函数或者 lambda 函数中引用变量时,会在当前嵌套的函数的名字空间中搜索,然后是父函数,然后是模块的名字空间。

在运行时,可以直接访问名字空间,局部名字空间 用 locals  来访问,全局名字空间用 globals  来访问。

例如:

def foo(x,y):    print(locals())    return 0

>>> foo(0,1)

>>> {'y': 1, 'x': 0}

在刚开启的IDLE中输入 globals() ,返回的结果是:{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}

即为此时的全局名字空间。包括模块中的变量和常量,导入到模块中的东西,函数以及类。

输入:

import sysfrom struct import unpackdef foo(x,y):    i = 90    print(locals())    return 0

再次输入 globals()  ,返回结果:

{'__builtins__': <module 'builtins' (built-in)>, '__package__': None, 'sys': <module 'sys' (built-in)>, '__name__': '__main__', 'foo': <function foo at 0x013BFAE0>, 'unpack': <built-in function unpack>, '__doc__': None}

其中import sys 和  from struct import unpack 的差别就出来了,


locals 的结果是只读的,如:

def fun(x):    i = 90    locals()['i'] = 78787    print(locals())    return 0

>>> fun(30)

{'i': 90, 'x': 30}
0

其中 i 的值并没有因为中间的赋值语句而改变。因为 locals() 返回的是一个拷贝。

又:

>>> i = 90

>>> globals()['i'] = 20

>>> i

20

这也是   globals  和  locals 的另一个区别

未导入其他模块时,在IDLE中运行 globals() 得到的结果如下:

{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}

一般情况下,想导入一个模块,只要 import 就行了,但在某些情况下,可能无法事先知道要导入的模块的名字,这时候就需要动态导入模块,

或者称之为 反射(由对象告诉我们他是什么),也叫自省。

此时要用到 函数 __import__('.....') ,

mod_name = __import__('......')

传入的是一个模块名字,返回值是这个模块,运行之后,模块已经被被映射到 globals() 中了,但映射的名称是 mod_name ,感觉效果类似于

import mod as mod_name

这时可以直接使用 mod_name 来调用模块中的方法等,也可以通过 getattr 来进行,

fun = getattr(mod_name, fun_name)

传入的参数可以是对象的方法或者属性的名字,返回对应的 方法 或者 属性实例,

如果没有该方法或者属性,则返回 AttributeError ,另有函数 callable(fun) 来判断 fun 是否是个可执行的函数

s = __import__('string')funlist = [ fun for fun in dir(s) if callable( getattr(s, fun)) ]

示例中,返回了 string 所有可调用的方法的列表