python中globals()_python中globals()的原因是什么?

在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()

我真的看不到这一点?我唯一需要它的时间是,如果我有局部变量和全局变量,它们都有相同的名称。

def F():

global x

x = 1

def G():

x = 5

print(x) #5

print(globals()["x"]) #1

F()

G()

但是您不应该遇到两个同名的变量的问题,并且需要在同一范围内同时使用这两个变量。

"但是你不应该遇到两个变量同名,并且需要在同一范围内使用它们的问题。"我不能这样想。这就是单独名称空间的全部原因,即在不同的作用域中具有相同名称的变量。当您使用其中两个名称时,重复的名称是很自然的事情,但不是问题,因为您可以给它们加前缀。

我来自C++家族,所以我不确定Python的人,但就我所能想到的,你不应该有一个没有唯一名称的全局变量。当然,在相同的范围内,会有一些变量具有相同的名称,这是我的愚蠢的句子,但不会有与本地变量同名的全局变量。那时候我会使用本地名称空间…但不知道,如果你这么说的话。

@玛希:以东十一〔0〕可能有点误导人。globals()本质上是模块的locals()。最接近于全局的python是__builtin__模块,它对您的所有程序都是真正全局的;您添加到该模块中的任何内容在任何地方的所有名称空间中都可用。

嗯,很好的补充,不是说我现在就需要它,但也许有一天会……谢谢)

Python为程序员提供了大量的工具来反思运行环境。这只是其中的一个,在一次解析会议上,它可以非常有用地看到全球范围内实际包含的目标。

我敢肯定,理性的背后是与使用EDOCX1〕〔5〕一样的,目的是看到变量在一个函数中定义,或使用dir来看到一个模块的内容或一个物体的属性。

从一个C+++背景来看,我可以理解,这些东西看起来不需要。在一个静态链接中,静态类型的环境中,它们将是绝对的。在这种情况下,在准确的时间编译变量是什么是全球性的,而一个物体的成员将拥有什么,甚至通过另一个编译单元导出什么名称。

在动态语言中,这些东西是不固定的;它们可以根据何种代码被导入而改变,或者甚至在运行时改变。由于这一原因,在一个解调器中获得这一信息的机会是不可估价的。

+ 1。此外,可以修改globals返回的字典(可能是留给专家最好的能力)。同样相关的是这句话"使用locals和globals函数,您可以动态地获取任意变量的值,将变量名作为字符串提供。"这反映了getattr函数的功能,它允许您通过以字符串形式提供函数名来动态访问任意函数。"

没有说你的回答比别人的好,但对我来说是。谢谢,我想我需要冷静下来,记住Python不是C++:谢谢大家的回答。

在locals()中更改元素通常不起作用。大多数python函数都没有局部变量的dict,所以当调用locals()时,它会构造局部变量当前值的dict;更改该dict不会反映到局部变量。有些情况下,函数执行"import*from xyz"(不再允许)之类的操作,即在编译时设置名称未知的局部变量;这些函数是用实际局部变量dict编译的,很久以前,所有函数都有实际局部变量dict,它们逐步消除了这种需要,我不知道在什么情况下您有一个dict现在。

当你需要用函数字符串命名函数时,它也很有用。For example:

ZZU1

我懂了。这是个好习惯吗?

如果函数有很多参数,比如def foo(a,b,c=false),该怎么办?如何将这些参数传递给globals()。

@ksooklall你照常把它传递给函数:用def foo(*args): print("hw", *args)你可以做:globals()['foo']()或globals()['foo']('reason', 42)等。

你可以把globals()和locals()的结果传达给eval,execfile和__import__指挥官。为这些命令创造一种限制性的环境,以便在那里工作。

因此,这些函数存在于支持其他函数的过程中,这些函数的效益来自于当前环境的不同潜力。例如,你可以叫globals(),然后在呼叫其中一个函数之前去除或添加一些变量。

如果你想评价一些参照范围内变量的代码,那么这些变量会出现在全球或地方。

为了扩展位,建筑物功能将解释给它的一条Python码。签名是:EDOCX1&3,你可以用它这样:

def foo():

x = 2

y = eval("x + 1", globals(), locals())

print("y=" + y) # should be 3

这篇作品,因为解释者从x中获得了locals()的价值。你可以用你自己的变量口令来评价。

下投者:请在评论中解释。

我不是第一个投反对票的人,但这并没有真正意义,你能给出一个更容易理解的示例代码吗?

当然,我已经扩展了我的答案。

有点奇怪,对我来说似乎没用,但也许这只是因为我对python不熟悉:p无论如何,谢谢。

由于其默认参数,eval("x+1")执行相同的操作;请参见help(eval)。

这里还有一个关于如何使用globals()的介绍:stackoverflow.com/a/22021058/9024698。

它还可以用于从字符串:

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)

它在"声明性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/—在这种情况下,对象主要是函数对象,但是来自函数对象(它们的名称、docstring和定义顺序)的元数据也构成了输入的一部分。这不是使用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模块都很有用,这样可以更容易地向数据添加项,而不必维护引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值