这个程序使用了Python有特色的语法套路。先看第一个。
main.py里的class MainWindow的函数init()中,有这样的语句:
self.scene.setMap((conf.w, conf.h), conf.mines)
这里的变量conf,定义在config.py中,由以下语句引入的:
from config import *
这里的conf.w,conf.h和conf.mines是什么呢?由此,转入config.py,一探究竟。
#module: config
import json
DEFAULTS = {
'splash':False,
'w': 10,
'h': 10,
'mines': 1,
'scores': [],
}
DEFAULT_SAVE_FILE = "config.cfg"
class _Conf:
def __getattr__(self,name):
return DEFAULTS[name]
def __setattr__(self,name,value):
if type(value) != type(DEFAULTS[name]):
raise Exception("%s %s is not %s:" %
(value, type(value), type(DEFAULTS[name])))
DEFAULTS[name] = value
def save(self,fileName=DEFAULT_SAVE_FILE):
with open(fileName, 'w+') as fp:
json.dump(DEFAULTS, fp, indent=True)
def load(self,fileName=DEFAULT_SAVE_FILE):
with open(fileName, 'r') as fp:
global DEFAULTS
DEFAULTS = json.load(fp)
conf = _Conf()
try:
conf.load()
except:
pass
由此可见,main.py导入该模块,会发生以下事情:
建立并初始化模块级变量,词典DEFAULTS;
建立并初始化模块级变量,DEFAULT_SAVE_FILE = "config.cfg"
建立模块级变量conf,并以此实例化 _Conf;
以conf引用 _Conf中的函数load(),把config.cfg文件中的数据,读入DEFAULTS。
遍观 _Conf,并没有成员变量w,h和mines,但为何使用conf.w,conf.h和conf.mines呢?
奥妙在于 _Conf中的特别函数 __getattr__(name)
当以conf.w读数据时,__getattr__ 的参数name的值,就是“w”,
而它返回的值,是DEFAULTS[“w”]。这个值等于10。
Python的这一语法套路,读取词典DEFAULTS的操作,表现形式成了访问class的成员。