当全局变量未定义时,如何初始化全局变量?

7

我有一个全局字典变量,将在被多次调用的函数中使用。我无法控制函数何时被调用,或者我正在编写的函数之外的范围。如果未初始化,我需要初始化该变量。一旦初始化,我将向其添加值。

global dict
if dict is None:
    dict = {}

dict[lldb.thread.GetThreadID()] = dict[lldb.thread.GetThreadID()] + 1

很抱歉,我得到了。
NameError: global name 'dict' is not defined

我知道应该先定义变量,但由于这段代码会被多次调用,如果只是简单地写 dict = {} ,那么每次调用时都会重新定义变量,除非我能够判断它是否已经定义,只有在未定义的情况下才进行定义。


2
你可以捕获 NameError 然后在那里设置它... 话虽如此,这似乎是一个奇怪的设计决定。你能提供更多的上下文吗? - mgilson
1
还有,这里发生了什么并不清楚……你的错误信息说“test2”,而你的代码中却是dict,并且在函数外使用了一个global语句……如果你能提供一个最小的可重现示例,那将非常有帮助。 - mgilson
是的,当断点被触发时,代码会被调试器执行。因此,调试器是调用代码的工具。另外,我是Python初学者 :( - user353877
抱歉,我在发布到StackOverflow上时重命名了变量,test2是一个错误,它应该只是dict。我已经更正了。 - user353877
只有这么少的上下文,很难弄清楚为什么需要全局变量以及这是否是最佳方法。我倾向于在模块开头定义全局变量(例如常量或某些状态相关变量,例如 my_dictionary = {}),然后在每个函数中需要时声明 global my_dictionary。作为一个经验法则,我不会使用保留关键字或内置类型名称作为变量名。 - Victor Domingos
@VictorDomingos 绝对是正确的,关于全局使用。这段代码由调试器调用,我正在尝试在这些调用之间保持一些上下文。 - user353877
2个回答

11

捕捉错误:

try:
    _ = myDict
except NameError:
    global myDict
    myDict = {}

重要提示:

不要使用dict或任何其他内置类型作为变量名。


4
针对楼主:底部的注释非常重要。 - Paul H
2
@PaulH -- 尤其是因为你必须执行一些非常糟糕的操作,才能使名称 dict 引发 NameError ... - mgilson
谢谢 :) 我认为它起作用了.. 它会给出一个警告SyntaxWarning: name 'myDict' is used prior to global declaration但这对我来说没问题。 - user353877

3
更加惯用的方法是预先将名称设置为一个标记值,然后针对该值进行检查:
_my_dict = None

...

def increment_thing():
    global _my_dict
    if _my_dict is None:
        _my_dict = {}
    thread_id = lldb.thread.GetThreadID()
    _my_dict[thread_id] = _my_dict.get(thread_id, 0) + 1

注意,我对lldb一无所知--但如果它使用了python线程,你最好使用threading.local:
import threading

# Thread local storage
_tls = threading.local()

def increment_thing():
    counter = getattr(_tls, 'counter', 0)
    _tls.counter = counter + 1

谢谢@mgilson :) 我也会尝试你的解决方案。我必须先弄清楚如何定义_my_dict的第一个定义,然后在调试器调用递增代码之前执行它。 - user353877

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接