Python 中 globals() 的原因?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12693606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:37:14  来源:igfitidea点击:

Reason for globals() in Python?

pythonglobal-variablesglobal

提问by

What is the reason of having globals() function in Python? It only returns dictionary of global variables, which are already global, so they can be used anywhere... I'm asking only out of curiosity, trying to learn python.

在 Python 中具有 globals() 函数的原因是什么?它只返回全局变量的字典,它们已经是全局的,所以它们可以在任何地方使用......我只是出于好奇而问,试图学习 python。

def F():
    global x
    x = 1

def G():
    print(globals()["x"]) #will return value of global 'x', which is 1

def H():
    print(x) #will also return value of global 'x', which, also, is 1

F()
G()
H()

I can't really see the point here? Only time I would need it, was if I had local and global variables, with same name for both of them

我真的看不出这里的重点?我唯一需要它的时候,是如果我有局部和全局变量,它们都具有相同的名称

def F():
    global x
    x = 1

def G():
    x = 5
    print(x) #5
    print(globals()["x"]) #1

F()
G()

But you should never run into a problem of having two variables with same name, and needing to use them both within same scope.

但是您永远不应该遇到具有相同名称的两个变量并且需要在同一范围内使用它们的问题。

采纳答案by Ian Clelland

Python gives the programmer a large number of tools for introspecting the running environment. globals()is just one of those, and it can be very useful in a debugging session to see what objects the global scope actually contains.

Python 为程序员提供了大量自省运行环境的工具。globals()只是其中之一,在调试会话中查看全局作用域实际包含哪些对象非常有用。

The rationale behind it, I'm sure, is the same as that of using locals()to see the variables defined in a function, or using dirto see the contents of a module, or the attributes of an object.

我敢肯定,其背后的原理与locals()用于查看函数中定义的变量、dir用于查看模块的内容或对象的属性的原理相同。

Coming from a C++ background, I can understand that these things seem unnecessary. In a statically linked, statically typed environment, they absolutely would be. In that case, it is known at compile time exactly what variables are global, and what members an object will have, and even what names are exported by another compilation unit.

来自 C++ 背景,我可以理解这些事情似乎没有必要。在静态链接、静态类型的环境中,它们绝对是。在这种情况下,在编译时就知道哪些变量是全局变量,一个对象将具有哪些成员,甚至另一个编译单元导出哪些名称。

In a dynamic language, however, these things are not fixed; they can change depending on how code is imported, or even during run time. For that reason at least, having access to this sort of information in a debugger can be invaluable.

然而,在动态语言中,这些事情并不是固定的。它们可以根据代码的导入方式甚至在运行时进行更改。至少出于这个原因,在调试器中访问此类信息是非常宝贵的。

回答by Richard Close

globals()is useful for eval()-- if you want to evaluate some code that refers to variables in scope, those variables will either be in globals or locals.

globals()非常有用eval()——如果你想评估一些引用范围内变量的代码,这些变量要么在全局变量中,要么在局部变量中。



To expand a bit, the eval()builtin function will interpret a string of Python code given to it. The signature is: eval(codeString, globals, locals), and you would use it like so:

稍微扩展一下,eval()内置函数将解释给它的一串 Python 代码。签名是: eval(codeString, globals, locals),你可以像这样使用它:

def foo():
    x = 2
    y = eval("x + 1", globals(), locals())
    print("y=" + y) # should be 3

This works, because the interpreter gets the value of xfrom the locals()dict of variables. You can of course supply your own dict of variables to eval.

这是有效的,因为解释器xlocals()变量的字典中获取值。你当然可以提供你自己的变量字典来评估。

回答by Bryan Oakley

You can pass the result of globals()and locals()to the eval, execfileand __import__commands. Doing so creates a restricted environment for those commands to work in.

你可以传递的结果globals(),并locals()evalexecfile__import__命令。这样做会为这些命令创建一个受限的环境。

Thus, these functions exist to support other functions that benefit from being given an environment potentially different from the current context. You could, for example, call globals()then remove or add some variables before calling one of those functions.

因此,这些功能的存在是为了支持其他功能,这些功能受益于给定一个可能与当前上下文不同的环境。例如,您可以globals()在调用这些函数之一之前调用然后删除或添加一些变量。

回答by Alex Soroka

It's also useful when you need to call a function using function's string name. For example:

当您需要使用函数的字符串名称调用函数时,它也很有用。例如:

def foo():
    pass

function_name_as_string = 'foo'

globals()[function_name_as_string]() # foo(). 

回答by greggo

It can be useful in 'declarative python'. For instance, in the below FooDefand BarDefare classes used to define a series of data structures which are then used by some package as its input, or its configuration. This allows you a lot of flexibility in what your input is, and you don't need to write a parser.

它在“声明性python”中很有用。例如,在下面的FooDefBarDef是用于定义一系列数据结构的类,然后某些包将这些数据结构用作其输入或配置。这允许您在输入内容方面具有很大的灵活性,并且您无需编写解析器。

# 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')

Note that this configuration file uses a loop to build up a list of names which are part of the configuration of Foo_other. So, this configuration language comes with a very powerful 'preprocessor', with an available run-time library. In case you want to, say, find a complex log, or extract things from a zip file and base64 decode them, as part of generating your configuration (this approach is not recommended, of course, for cases where the input may be from an untrusted source...)

请注意,此配置文件使用循环来构建名称列表,这些名称是Foo_other. 因此,这种配置语言带有一个非常强大的“预处理器”,以及一个可用的运行时库。如果您想查找复杂的日志,或者从 zip 文件中提取内容并对其进行 base64 解码,作为生成配置的一部分(当然,对于输入可能来自来源不可信...)

The package reads the configuration using something like the following:

该包使用如下内容读取配置:

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

So, finally getting to the point, globals()is useful, when using such a package, if you want to mint a series of definitions procedurally:

所以,最后切入globals()正题,在使用这样的包时,如果你想在程序上创建一系列定义,这是很有用的:

for idx in range(20):
    varname = "Foo_%02d" % i
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)

This is equivalent to writing out

这相当于写出

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 ...

An example of a package which obtains its input by gathering a bunch of definitions from a python module is PLY (Python-lex-yacc) http://www.dabeaz.com/ply/-- in that case the objects are mostly function objects, but metadata from the function objects (their names, docstrings, and order of definition) also form part of the input. It's not such a good example for use of globals(). Also, it is imported by the 'configuration' - the latter being a normal python script -- rather than the other way around.

PLY (Python-lex-yacc) http://www.dabeaz.com/ply/——在这种情况下,对象主要是函数对象,但来自函数对象的元数据(它们的名称、文档字符串和定义顺序)也构成输入的一部分。这不是使用globals(). 此外,它是由“配置”导入的——后者是一个普通的 python 脚本——而不是相反。

I've used 'declarative python' on a few projects I've worked on, and have had occasion to use globals()when writing configurations for those. You could certainly argue that this was due to a weakness in the way the configuration 'language' was designed. Use of globals()in this way doesn't produce very clear results; just results which might be easier to maintain than writing out a dozen nearly-identical statements.

我在我参与过的一些项目中使用了“声明性 python”,并且globals()在为这些项目编写配置时有机会使用它。您当然可以争辩说,这是由于配置“语言”的设计方式存在缺陷。使用globals()这种方式不会产生很明显的效果; 只是结果可能比写出十几个几乎相同的语句更容易维护。

You can also use it to give variables significance within the configuration file, according to their names:

您还可以使用它根据名称在配置文件中赋予变量意义:

# 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")

This method could be useful for anypython module that defines a lot of tables and structures, to make it easier to add items to the data, without having to maintain the references as well.

此方法对于定义大量表和结构的任何Python 模块都非常有用,可以更轻松地向数据添加项目,而无需维护引用。

回答by Bart

It can also be used to get an instance of the class 'classname' from a string:

它还可以用于从字符串中获取类 'classname' 的实例:

class C:
    def __init__(self, x):
        self.x = x
        print('Added new instance, x:', self.x)


def call(str):
    obj = globals()[str](4)
    return obj

c = call('C')
print(c.x)

回答by Maksym Ganenko

It might be useful if you like to import module you just have built:

如果您想导入刚刚构建的模块,它可能会很有用:

a.py

一个.py

[...]

def buildModule():
    [...code to build module...]
    return __import__("somemodule")

[...]

b.py

b.py

from a import buildModule

def setup():
   globals()["somemodule"] = buildModule()

回答by roachsinai

Not really. Global variables Python really has are module-scoped variables.

并不真地。Python 真正拥有的全局变量是模块范围的变量。

# a.py
print(globals())

import b
b.tt()
# b.py
def tt():
    print(globals())

run python a.py, at least two output of globals()['__name__']is different.

run python a.py,至少有两个输出globals()['__name__']是不同的。

Code herein cpython on Github shows it.

代码这里在Github上CPython的显示它。