近几个月在公司做一个新项目,因为公司的C++框架有一点问题,项目又不大,所以我选用了Python做开发语言。事实上我没怎么写过Python,在做这个项目期间也学习不少新的知识,也对一些知识有了新的体会。比如今天要说的全局变量,以前看过的很多书和文章都有说过要尽量少用。但是因为平时写C++确实用得太少所以体会并不深,而这次在上面吃了亏,就深有体会了。
在写Python的时候,接触到了模块的概念。从网上得知,可将模块当做单例使用。比如我需要有一些配置要给其它模块使用。
# config.py
g_user = 'admin'
def get_user():
return g_user
当其它文件需要使用配置的时候,只需要import config而可以使用了,而Python的模块机制又保证它只会存在一份。比如有个other模块根据配置的user不同,来初始化一个全局变量:
# other.py
import config
class Test:
def __init__(self, user):
self.user = user
g_obj = Test(config.get_user())
对于常量的话这么使用是没有什么问题的。但很多时候,我们会需要从外部去读取配置信息。将上面的config改为:
# config2.py
g_user = ''
def load():
# 从数据库或文件读取user
...
def get_user():
return g_user
同时main文件为:
# main.py
import config2
import other
if __name__ == '__main__':
config2.load()
other模块的目的是根据配置的用户进行相应的初始化。但实际上other读取到永远都是config2中初始化时的空字符串。
那么问题出在哪呢?就出在main中。因为main顶部同时引入了other和config2。此时的config2事实上还没进行load,而other中的全局变量已经就使用上了config2里的值了。后续运行到load的时候,因为other里的g_obj已经初始化完毕了,那么load后的值也与它无关了。
这个例子比较简陋,看起来不怎么合理。实际上是我从实际代码里抽象出来的。当我踩到这个坑的时候,那一刻我深刻体会到了,尽量少用全局变量,因为全局变量初始化顺序的不同可能会导致出错。
这里面还有另外一个问题,就是我对Python的理解不到位,没有选用适当的方法和代码结构去实现。这方面急不来,还需要学习与经验积累。