1.1 最小化from *的破坏
from *会把所有变量名复制出去,导入者可能得到超出它需要的分布(包括会覆盖导入者内的变量名的变量名)。
在__init__.py中使用__all__则可以保证from *语句只会把__all__列表中的这些变量名复制出来。另外对于模块中以_x形式的变量是指出不被复制的变量名。
1.2混合用法模型:__name__和__main__
每个模块都有一个名为__main__的内置属性,python会自动设置该属性:
- 如果文件是以顶层程序文件执行,在启动时,__name__就会设备为字符串"__main__"。
- 如果文件被导入,__name__就会改成客户端所了解的模块名。
结果就是模块可以检测自己的__name__,来确定他是执行还是在导入。
1.3 以__name__进行单元测试
这就是在pycharm中常用的方法:
if __name__ == '__main__': #这种语法来进行单元测试
import sys
if len(sys.argv) ==1: # sys.argv列表包含了命令行参数,是一个字符串列表,其中你第一个总是将要运行的脚本名
print('without argv')
else:
print(sys.argv[1])
其实,更多的在平时看到的可能是使用argparse模块。argparse是一个命令行工具,具体用法如下:
# learn to using argparse and parse cmdline
def parse_arg():
# generate a parse object,description will describe what's this parse resolver,
# you can see this string when using help
parser =argparse.ArgumentParser(description='this is a demo of argparse')
# using add_argument to add argument, '-n' and '-name' are behalf of the same arg
parser.add_argument('-n','--name',default='Ssozh',help='write down your name')
# finally , use args get the arguments
args = parser.parse_args()
print(args) # Namespace(name='Ssozh') ,which means -n cannot represent argument name
name = args.name # using name rather than n
return name
if __name__ == '__main__':
name = parse_arg()
print('hello {}'.format(name))
更详细的可以见另一篇博文:http://vra.github.io/2017/12/02/argparse-usage/
1.4 模块是对象:元程序
因为模型通过内置属性显示了它们的大多数有趣特性,因此,很容易编写程序来管理其他程序。我们通常称这类管理程序为元程序(metaprogram),因为它们是在其他系统之上工作的。
例如,我们编写了一个元程序用来查看模块a的内置属性,而模块(python文件)的内置属性使用属性字典保存,可以使用__dict__进行索引运算。
def listing(module, verbose=True):
sepline = '-' * 60 # sepline = '________________'
if verbose:
print(sepline)
# name: 123 file: D:\Ssozh\PyCharm\logo_test\module_demo.py
print('name:', module.__name__, 'file:', module.__file__)
print(sepline)
count = 0
for attr in module.__dict__: # get the attr of module
# 00)__name__
print('%02d)%s' % (count, attr), end=' ')
if attr.startswith('_'):
print('<built-in name>') # <built-in name>
else:
print(getattr(module, attr)) # this attr maybe variable
count += 1
if verbose:
print(sepline)
# 123 has 8 names
print(module.__name__, 'has %d names' % count)
print(sepline)
1.5 模块设计理念
- 总是在Python的模块内编写代码。事实上,在交互模型提示符下输入的程序代码,其实是存在于内置模型__main__之内的。交互模型提示符独特之处就在于程序是执行后就立刻丢弃,以及表达式结果是自动打印的。
- 模块耦合要降到最低:全局变量。就像函数一样,如果编写成闭合的盒子,模块运行得最好。原则就是,模块应该尽可能和其他模块的全局变量无关,除了与从模块导入的函数和类。
- 最大化模块的黏合性:统一目标。可以通过最大化模块的黏合性来最小化模块的耦合性。如果模块的所有元素都享有共同的目的,就不太可能依赖外部的变量名。
- 模块应该少去修改其他模块的变量。