在Python中存储和使用大文本文件的最佳方式
我正在用Python创建一个网络服务器,做一个类似“拼字游戏”的程序。这个服务器可以接收用户,解决游戏中的拼字板,并给玩家的输入打分。我使用的字典文件有1.8MB(是ENABLE2K字典),我需要让几个游戏解决器类都能使用这个字典。目前,我的做法是让每个类逐行读取文件,并生成一个哈希表(就是一种特殊的数组),但是我实例化的解决器类越多,占用的内存就越多。
我想做的是只导入一次字典文件,然后在每个解决器实例需要的时候把它传过去。但是,最好的做法是什么呢?我应该在全局空间导入字典,然后在解决器类里用globals()['dictionary']来访问它吗?还是应该先导入字典,然后把它作为参数传给类的构造函数?这两种方法哪个更好?还有没有其他的选择呢?
4 个回答
亚当,记住在Python中,当你这样写:
a = read_dict_from_file()
b = a
... 其实你并不是在真正地复制 a
,所以不会占用更多的内存,你只是让 b
变成了指向同一个对象的另一个引用。
所以基本上,你提到的任何解决方案在内存使用上都会好得多。简单来说,就是只需读取一次字典,然后保持对它的引用。无论你是用全局变量,还是把它传给每个实例,或者其他方式,你都在引用同一个对象,而不是重复创建。
那么,哪种方式最符合Python的风格呢?这又是另一个复杂的问题,但我个人会这样做:
def main(args):
run_initialization_stuff()
dictionary = read_dictionary_from_file()
solvers = [ Solver(class=x, dictionary=dictionary) for x in len(number_of_solvers) ]
希望这对你有帮助。
虽然现在它基本上是一个单例,但通常对全局变量的反对意见仍然适用。如果你想找一个更符合Python风格的单例替代品,可以看看“borg”对象。
这其实就是唯一的区别。一旦字典对象创建出来,你在传递它的时候只是绑定了新的引用,除非你特别进行深拷贝。只要每个求解器实例不需要私有的可修改副本,这样一次性在中心构建它是很合理的。
如果你创建一个叫做 dictionary.py 的模块,里面有代码用来读取文件并构建一个字典,这段代码只会在第一次导入这个模块的时候执行。之后再导入这个模块时,系统会返回一个对已经存在的模块实例的引用。这样,你的类就可以:
import dictionary
dictionary.words[whatever]
其中 dictionary.py 的内容是:
words = {}
# read file and add to 'words'