关于python:为什么人们会使用globals()来定义变量

Why would people use globals() to define variables

我最近在我们的代码中遇到了很多这样的地方

1
2
3
4
...
globals()['machine'] = otherlib.Machine()
globals()['logger'] = otherlib.getLogger()
globals()['logfile'] = datetime.datetime.now().strftim('logfiles_%Y_%m_%d.log')

我不明白为什么人们会这样做,而不是这样做

1
2
global machine
machine = otherlib.Machine()

等等。

这里有一个稍微匿名的功能,它可以完全做到这一点:

1
2
3
4
5
6
7
8
9
10
11
def openlog(num)
    log_file = '/log_dir/thisprogram.' + num
    if os.path.exists(log_file):
        os.rename(log_file, log_file + '.old')

    try:
        globals()["log"] = open(log_file, 'w')
        return log
    except:
       print 'Unable to open ' + log_file
       sys.exit(1)

它混淆了皮林特(0.25)和我的地狱。

有什么理由用这种方式编码吗?在我们的代码中,eval的用法是最少的,而这不在库中

ps我在python中检查了globals()的原因,但它并没有真正回答为什么要用它来设置程序中的globals。


也许函数使用了与全局变量同名的局部变量,而程序员不想更改变量名?

1
2
3
def foo(bar):
    global bar # SyntaxError
    bar = bar + 1
1
2
3
4
def foo(bar):
    globals()['bar'] = bar + 1
foo(1)
print(bar) # prints 2

另一个用例是动态定义变量名,尽管仍然有点似是而非(显然不是您给出的示例函数中的情况)。这很少是一个好主意,如果有的话,但至少在这个网站上有很多问题。例如:

1
2
3
4
5
6
7
8
9
10
>>> def new_variable():
...     name = input("Give your new variable a name!")
...     value = input("Give your new variable a value!")
...     globals()[name] = value
...
>>> new_variable()
Give your new variable a name! foo
Give your new variable a value! bar
>>> print(foo)
bar

否则,我只能想到一个原因:也许一些监督实体要求所有全局变量都以这种方式设置,例如,"为了真正清楚地表明这些变量是全局的"。或者同一个监督实体已经全面禁止了global关键字,或者码头程序员为每一行付费。

我并不是说这其中任何一个都是一个好的理由,但是再一次地,我真的不能想象一个好的理由来定义变量,如果不是为了范围界定的目的(即使那样,这似乎是有问题的…)。

为了以防万一,我做了一个定时检查,看看globals()调用是否比使用关键字更快。我希望函数调用+字典访问速度会明显减慢,事实就是这样。

1
2
3
4
5
6
7
8
>>> import timeit
>>> timeit.timeit('foo()', 'def foo():
\tglobals()["bar"] = 1'
,number=10000000)
2.733132876863408
>>> timeit.timeit('foo()', 'def foo():
\tglobal bar
\tbar = 1'
,number=10000000)
1.6613818077011615

考虑到您发布的代码和我的计时结果,我想不出任何合理的理由来让您希望这样编写代码。看起来要么管理要求有误,要么就是单纯的无能。


作者是PHP转换者吗?这是PHP中的有效代码:

1
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];

请参阅此了解更多示例。如果有人习惯了这种编写代码的方式,也许他们只是使用了与之最接近的Python匹配的方式,而不需要检查其他方法。

有时,您会使用一个超全局的$GLOBAL变量来定义某些内容,因为尽管php中存在global关键字,但它只会导入现有的变量——据我所知,它无法创建新的变量。