Python:用类变量替换全局变量是否“合适”

时间:2014-10-14 03:29:16

标签: python global-variables class-variables

请善待我,我是Python的初学者: - )

现在,我看到编写Python程序的'最佳实践'是将主代码包装在'main'函数中,并执行if "__main__" == __name__:测试以调用'main'函数。

这当然导致必须在'main'函数中使用一系列global语句来访问全局变量。

我想知道它是否更合适(或者'Pythonic',如果你愿意的话)将全局变量收集到一个自定义类中,比如_v,并使用_v.前缀来引用变量?

另外,作为一个必然结果的问题,是否会对绩效或异常处理产生负面影响?


编辑:以下是该计划的一般结构:

paramset = {
    0: { ...dict of params... }
    1: { ...dict of params... }
    2: { ...dict of params... }
    }

selector = 0
reset_requested = False
selector_change = False

def sighup_handler(signal,frame):
    global reset_requested
    logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
    reset_requested = True
    selector = 0

def sigusr1_handler(signal,frame):
    global selector
    new_selector = (selector + 1) % len(paramset)
    logger.info('Caught SIGHUP, changing parameters to set #{0}'.format(new_selector))
    selector = new_selector
    selector_change = True

signal.signal(signal.SIGHUP, sighup_handler)
signal.signal(signal.SIGUSR1, sigusr1_handler)

def main():
    global reset_requested
    global selector
    global selector_change
    keep_running = True
    while keep_running
        logger.info('Processing selector {0}'.format(selector))
        for stage in [process_stage1, process_stage2, process_stage3]
            err, result = stage(paramset[selector])
            if err is not None:
                logger.critical('Stage failure! Err {0} details: {0}'.format(err, result))
                raise SystemError('Err {0} details: {0}'.format(err, result))
            else:
                logger.info('Stage success: {0}'.format(result))
            if reset_requested:
                stage_cleanup()
                reset_requested = False
            else:
                inter_stage_pause()
                if selector_change:
                    selector_change = False
                    break
        selector = (selector + 1) % len(paramset)

2 个答案:

答案 0 :(得分:2)

示例代码中缺少足够的部分,难以得出任何确定的结论。

事件驱动的方法

此类问题的常用方法是使其完全由事件驱动。就目前而言,代码主要是轮询。例如,sighup_handler在请求的reset_requested = True进程中设置whilemain循环。事件驱动的方法将处理重置,即直接调用stage_cleanup

def sighup_handler(signal,frame):
    logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
    stage_cleanup()


具有共享变量的类

在示例代码中,所有那些process_stages和循环阶段的目的尚不清楚。这一切都可以放在事件驱动的环境中吗?我不知道。如果它不能并且确实需要共享变量,那么您对类的建议将是一个自然的选择。这类课程的开头可能如下:

class Main(object);

    def __init__(self):
        self.selector = 0
        self.selector_change = False
        signal.signal(signal.SIGHUP, self.sighup_handler)
        signal.signal(signal.SIGUSR1, self.sigusr1_handler)

    def sighup_handler(self, signal,frame):
        logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
        stage_cleanup() 
        self.selector = 0

    def sigusr1_handler(self, signal,frame):
        new_selector = (selector + 1) % len(paramset)
        logger.info('Caught SIGHUP, changing parameters to set #{0}'.format(new_selector))
        self.selector = new_selector
        self.selector_change = True

    def mainloop(self):
        # Do here whatever polling is actually required.

if __name__ == '__main__':
    main = Main()
    main.mainloop()

同样,因为我不清楚轮询循环的真正目的,所以我没有尝试在上面的类中重现它的功能。

答案 1 :(得分:0)

通常,最佳做法是避免全局变量,而只是通过方法调用将变量传递给需要它们的类/方法。示例:如果要创建计算器,请创建一个需要2个int的加法方法并返回一个int。这与将2个输入整数和1个输出int作为全局变量形成对比,并且使用add方法可以处理这些变量。