Python 如何优雅地处理全局变量?

Python 如何优雅地处理全局变量?,python,Python,在多线程环境中,flag1和flag2是布尔值(全局变量),可以在其他地方修改。如果我能这样做,那将非常优雅: def doSomething(index): if index == 0: while flag1: do stuff elif index == 1: while flag2: do stuff ... from enum import Enum class Flags(E

在多线程环境中,
flag1
flag2
是布尔值(全局变量),可以在其他地方修改。如果我能这样做,那将非常优雅:

def doSomething(index):
    if index == 0:
        while flag1:
            do stuff
    elif index == 1:
        while flag2:
            do stuff

    ...
from enum import Enum

class Flags(Enum):
    flag0 = 0
    flag1 = 1
    flag2 = 2
    flag3 = 3
    def __init__(self, value):
        self._boolean = False
    def __nonzero__(self):
        return self._boolean
    def set(self):
        "make the flag be True"
        self._boolean = True
    def clear(self):
        "make the flag be False"
        self._boolean = False

print Flags.flag0, bool(Flags.flag0)
Flags.flag0.set()
print Flags.flag0, bool(Flags.flag0)

the_flag_I_care_about = Flags.flag1
print the_flag_I_care_about, bool(the_flag_I_care_about)
the_flag_I_care_about.set()
print the_flag_I_care_about, bool(the_flag_I_care_about)
the_flag_I_care_about.clear()
print the_flag_I_care_about, bool(the_flag_I_care_about)
有没有办法做到这一点

编辑:

1.看到一些人在建议列表,事情是,像这样的列表
flags=[flag1,flag2,flag3,…]
假设
flag1=True
flag2=False
flag3=True
,这使得
flags=[True,False,True]
,如果您在另一个线程的其他地方修改了
flag1=False
flags
将不会相应地更改,因此这肯定不起作用

2。事实上,我发现一个原始答案建议
,而[flag1,flag2,flag3,…][index]
,而且它确实有效!只是不知道他为什么删除了他的答案

有趣的部分:

刚刚测试了以下部分:

def doSomething(index):
    while (put either flag1 or flag2 here according to index):
        do stuff
这是行不通的,但有趣的是,这确实有效:

def doSomething(index):
    flags = [flag1, flag2, flag3]
    while flags[index]:
        do stuff

所以我假设
[flag1,flag2,flag3][index]
实际返回原始变量?任何人都可以再解释一下吗?

您可以使用
三值操作符

def doSomething(index):
    while [flag1, flag2, flag3][index]:
        do stuff

如果可以有多个
索引
值,则有一个标志列表:

def doSomething(index):
    while (flag1 if index else flag2):
        do stuff
然后可以使用索引查询相应的标志:

flags = [flag0, flag1, flag2, flag3, flag4]
编辑

为此,全局变量不是
flag0
flag1
等,而是列表中的
flags
。然后线程修改
标志[flag1]
flag1
1

def doSomthing(index):
    while(flags[index]):
        do_stuff()
或者,要使用新的
Enum
模块():


哦,说得清楚一点——使用比
flag0
等更好的名称:)

来扩展伊桑的答案:

您可以有一个所有索引的列表,然后像这样构造
while
语句:

def doSomething(index):
    if index == 0:
        while flag1:
            do stuff
    elif index == 1:
        while flag2:
            do stuff

    ...
from enum import Enum

class Flags(Enum):
    flag0 = 0
    flag1 = 1
    flag2 = 2
    flag3 = 3
    def __init__(self, value):
        self._boolean = False
    def __nonzero__(self):
        return self._boolean
    def set(self):
        "make the flag be True"
        self._boolean = True
    def clear(self):
        "make the flag be False"
        self._boolean = False

print Flags.flag0, bool(Flags.flag0)
Flags.flag0.set()
print Flags.flag0, bool(Flags.flag0)

the_flag_I_care_about = Flags.flag1
print the_flag_I_care_about, bool(the_flag_I_care_about)
the_flag_I_care_about.set()
print the_flag_I_care_about, bool(the_flag_I_care_about)
the_flag_I_care_about.clear()
print the_flag_I_care_about, bool(the_flag_I_care_about)
您说过您编辑了flag1和flag2对象(我假设在代码的其他部分中),并且它们在列表中没有更改。您只需在
while
循环之前重新构建列表:

while flags[index]:
    # do stuff

要使用您描述的“switch”语句,您需要访问
doSomething
函数中的所有标志变量,因此重构列表是很简单的。

对于这个问题,可能有一个更优雅的设计解决方案,但要避开列表中没有更新的变量,只需将它们包装在
类中

while [flag1, flag2, flag3, ...][index]:
    # do stuff

我相信当你们创建引用列表或字典时,文字的引用不会改变

创建标志列表时,
flags[0]
指向
flag1
所指向的,即
False

当您将值重新分配给
flag1
时,您正在更改
flag1
所指向的内容,但
flags[0]
仍指向
False

解决这个问题的一种方法是再添加一层对象包装器。如果布尔值包含在对象中,由于列表中的引用指向标签所指向的对象,因此将反映字段中的更改

事实上,为什么不直接使用
标志
作为全局变量呢?如果脚本足够聪明,可以在特定位置的一个特定标志中硬编码更改,也许我们可以替换

>>> class Flag():
    def __init__(self,flag):
        self.flag = flag


>>> flag_1 = Flag(True)
>>> flag_2 = Flag(False)
>>> flag_list = [flag_1, flag_2]
>>> flag_1.flag = False
>>> flag_list[0].flag
False

甚至在传递信息的情况下

flags[0] = False

标志可以是列表、dict或普通对象。到处都是好消息传递方式

这行不通
flag0
flag1
在其他地方修改,但是
flags
(列表)不会相应更改,但它是一个引用列表;列表中的值是实际标志变量的值+1.这不是一个参考列表!Python列表是按值传递的,除了类。@Shane:我很抱歉没有清楚地解释我自己--
标志
是用来替换全局变量的。我还添加了一个使用新的
Enum
数据类型的示例。看起来只有
value\u one
value\u two
两个选项?是的,ternaries只提供两个选项。你想要一个while语句,它可以在一行中处理一系列不同的选择吗?嗯,是的,这就是为什么我想找到一种优雅的方法。不,这不起作用,请参阅我的编辑。唯一可行的方法就是把列表直接组织成while语句,我仍然不知道为什么那个家伙会用这个删除他的答案。是的,它会奏效。我只是推荐了和你说的完全一样的东西,格式稍微不同。每次都要在函数中重建列表。唯一不同的是,为了清晰起见,我创建了一个变量,而另一个人没有将重构的列表存储在变量中。我认为Shane希望避免创建不必要的包装类,因为他可能已经将代码配置为使用不同的类。@ThomasHobohm,这就是为什么我强调这似乎更像是一个设计问题,并且看起来这有助于重构以实现所需的效果(请参见全局标志之间的高度耦合——如果它们更改了类或类型等怎么办?)你知道他帖子中的代码只是一个例子,对吧?@ThomasHobohm你的意思是
dostuff
不是有效的python语法吗?:)我的意思是,他可能有更复杂的代码,重构需要更长的时间。他还使用了多线程,因此他可能无法在不使这些变量全局化的情况下将这些变量轻松地传递给所有不同的线程;局部变量也可能需要同样的流。你能想出一个更好的题目吗?
flags[mess] = False