Python:是';适当的';用类变量替换全局变量的步骤
请善待我,我是Python初学者:-) 现在,我看到编写Python程序的“最佳实践”是将主代码包装在“main”函数中,并执行Python:是';适当的';用类变量替换全局变量的步骤,python,global-variables,class-variables,Python,Global Variables,Class Variables,请善待我,我是Python初学者:-) 现在,我看到编写Python程序的“最佳实践”是将主代码包装在“main”函数中,并执行如果“\uuuu main\uuuu”==\uu name:测试以调用“main”函数 当然,这就需要在“main”函数中使用一系列global语句来访问全局变量 我想知道将全局变量收集到一个自定义类(比如\u v)中,并使用\u v.前缀引用变量是否更合适(或者“Pythonic”,如果您愿意的话) 另外,作为一个必然的问题,这会对性能或异常处理产生任何负面影响吗
如果“\uuuu main\uuuu”==\uu name:
测试以调用“main”函数
当然,这就需要在“main”函数中使用一系列global
语句来访问全局变量
我想知道将全局变量收集到一个自定义类(比如\u v
)中,并使用\u v.
前缀引用变量是否更合适(或者“Pythonic”,如果您愿意的话)
另外,作为一个必然的问题,这会对性能或异常处理产生任何负面影响吗
编辑:以下是程序的一般结构:
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个整数并返回一个整数。这与将2个输入整数和1个输出整数作为全局变量,并让add方法处理这些变量形成对比。示例代码中缺少足够多的片段,因此很难得出任何确定的结论 事件驱动方法 解决这类问题的通常方法是使其完全由事件驱动。目前,代码主要是轮询。例如,
sighup\u处理程序
设置reset\u requested=True
,而main
中的循环处理该请求。事件驱动方法将处理重置,这意味着直接调用stage\u cleanup
:
def sighup_handler(signal,frame):
logger.info('Caught SIGHUP, resetting to set #{0}'.format(new_selector))
stage_cleanup()
使用共享变量初始化
在示例代码中,所有这些过程_阶段以及在这些阶段中循环的目的都不清楚。所有这些都可以放在事件驱动的上下文中吗?我不知道。如果不能,并且确实需要共享变量,那么您对类的建议将是一个自然选择。此类课程的开始可能如下所示:
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()
同样,因为我不清楚轮询循环的真正用途,所以我没有尝试在上面的类中重现它的功能。好吧,在我的情况下的“用例”是我必须截获几个信号(HUP、USR1和USR2),这些信号将激活一些标志,这些标志将由main()函数“在适当的时候”处理(即,向程序发送这些信号不会立即产生结果).在python中,诸如HUP、USR1之类的信号是使用信号
模块进行截获的。文档。不需要全局变量。我知道。信号处理程序只设置一个标志。主函数中的主循环将定期检查标志,并在启动长流程之前更改流程的各种参数pepoluan,你能给我们看看你的代码(或它的最小工作子集)吗?如果我们看到您的尝试,我们将更容易提供有用的反馈。谢谢。我会在下班后编辑我的问题。@John1024我编辑了我的问题,只添加了相关的逻辑。谢谢。这不是一个问题,但很有助于了解问题的动机。感谢您的解释!活动dri遗憾的是,ven信号处理方法不适用,因为当请求重置时,如果某个阶段仍在运行,则该阶段必须运行到完成。这就是为什么我只在信号处理程序中设置一个标志,并让主循环处理阶段之间的标志。@pepoluan事件驱动信号处理程序设计用于处理问题类似于此。如果在“阶段”期间不能处理重置正在运行时,解决方案是在关键部分对HUP信号进行该阶段的处理,然后稍后将其取消阻止。甚至还有一种方法可以查看。信号处理是一门发展良好的艺术。嗯……这对我来说是新的。感谢链接!我刚刚注意到这些链接需要py3.3。如果您使用的是较旧版本的python,可能会有所帮助。