它在“声明性 python”中很有用。例如,在下面FooDef
和BarDef
是用于定义一系列数据结构的类,然后某些包将这些数据结构用作其输入或配置。这使您在输入内容方面具有很大的灵活性,并且您无需编写解析器。
# FooDef, BarDef are classes
Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )
namelist = []
for i in range(6):
namelist.append("nm%03d"%i)
Foo_other = FooDef("a third one", string_list = namelist )
Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')
请注意,此配置文件使用循环来构建名称列表,这些名称是Foo_other
. 因此,这种配置语言带有一个非常强大的“预处理器”,带有一个可用的运行时库。如果您想查找复杂的日志,或者从 zip 文件中提取内容并进行 base64 解码,作为生成配置的一部分(当然,对于输入可能来自不受信任的来源...)
该包使用以下内容读取配置:
conf_globals = {} # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef # ... on .DefBase
fname = "user.conf"
try:
exec open(fname) in conf_globals
except Exception:
...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).
defs = {}
for nm,val in conf_globals.items():
if isinstance(val,mypkgconfig.DefBase):
defs[nm] = val
所以,最后切入globals()
正题,在使用这样的包时,如果你想在程序上创建一系列定义,这很有用:
for idx in range(20):
varname = "Foo_%02d" % i
globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)
这相当于写出
Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...
PLY (Python-lex-yacc) http://www.dabeaz.com/ply/是通过从 python 模块收集一堆定义来获取其输入的包的一个示例 ——在这种情况下,对象主要是函数对象,但来自函数对象的元数据(它们的名称、文档字符串和定义顺序)也构成输入的一部分。这不是使用globals()
. 此外,它是由“配置”导入的——后者是一个普通的 python 脚本——而不是相反。
我在一些我从事过的项目中使用了“声明性 python”,并且在globals()
为这些项目编写配置时有机会使用。您当然可以争辩说,这是由于配置“语言”的设计方式存在缺陷。以这种方式使用globals()
不会产生非常清晰的结果;只是结果可能比写出十几个几乎相同的语句更容易维护。
您还可以使用它根据名称在配置文件中赋予变量重要性:
# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist = BarDef( foo_k , method = "kset")
此方法对于定义大量表和结构的任何python 模块都很有用,可以更轻松地将项目添加到数据中,而无需维护引用。