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

时间:2014-07-31 02:25:12

标签: python

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

    ...

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

def doSomething(index):
    while (put either flag1 or flag2 here according to index):
        do stuff

有没有办法实现这个目标?

修改

1。看到一些人建议列表,事情就是这样的列表flags = [flag1, flag2, flag3, ...]假设flag1 = Trueflag2 = Falseflag3 = True,这会产生flags = [True, False, True],如果您在另一个帖子中的其他位置修改flag1 = Falseflags也不会相应地更改,所以这肯定不会起作用。

enter image description here

2。实际上,我发现一个原始答案暗示while [flag1, flag2, flag3, ...][index],它确实有效!只是不知道为什么他删除了他的答案?

有趣的部分:

刚刚测试了以下部分:

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

WON&#T; T,但有趣的是,这确实有效:

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

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

5 个答案:

答案 0 :(得分:2)

我相信当您创建列表或参考字典时会发生什么,文字的引用不会改变。

当您创建标记列表时,flags[0]指向flag1指向的内容,即False

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

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

事实上,为什么不将flags用作全局变量呢?如果脚本足够智能,可以在特定位置硬编码某个特定标志的更改,那么我们可以替换

flag1 = False

flags[0] = False

或甚至通过消息传递

flags[mess] = False

flags可以是list,dict或普通对象。遍布整个地方的好消息传递方式!

答案 1 :(得分:1)

这个问题可能有更优雅的设计解决方案,但为了解决列表中未更新的变量,只需将它们包装在class

中即可。
>>> 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

答案 2 :(得分:0)

您使用ternary运算符。

def doSomething(index):
    while (flag1 if index else flag2):
        do stuff

答案 3 :(得分:0)

如果您可以有多个index值,那么请有一个标志列表:

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

然后您可以使用索引查询相应的标志:

def doSomthing(index):
    while(flags[index]):
        do_stuff()

修改

为此,全局变量 flag0flag1等,而是全局变量flags,即列表。然后线程修改flags[flag1]flag11

FLAG0, FLAG1, FLAG2, FLAG3 = range(4)
flags = [False] * 4

或者,要使用新的Enum模块(enum34 is the backport):

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)

哦,只是要清楚 - 使用比flag0更好的名字,等等。)

答案 4 :(得分:0)

扩展Ethan的答案:

您可以拥有所有索引的列表,然后按照以下方式构建while语句:

while flags[index]:
    # do stuff

你说你编辑了flag1和flag2对象(在代码的其他部分,我假设),并且它们在列表中没有变化。您可以在while循环之前重建列表:

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

要获得您所描述的“switch”语句,您无论如何都需要访问doSomething函数内的所有标志变量,因此重建列表将是微不足道的。