一.模块
1.包与模块:
为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。一个
abc.py
的文件就是一个名字叫abc
的模块,一个xyz.py
的文件就是一个名字叫xyz
的模块。假设我们的abc
和xyz
这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如mycompany
,按照如下目录存放:
mycompany
├─ __init__.py
├─ abc.py
└─ xyz.py
2.多级目录:
引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,
abc.py
模块的名字就变成了mycompany.abc
,类似的,xyz.py
的模块名变成了mycompany.xyz
。每一个包目录下面都会有一个__init__.py
的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py
可以是空文件,也可以有Python代码,因为__init__.py
本身就是一个模块,而它的模块名就是mycompany。
类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:
mycompany
├─ web
│ ├─ __init__.py
│ ├─ utils.py
│ └─ www.py
├─ __init__.py
├─ abc.py
└─ utils.py
文件www.py
的模块名就是mycompany.web.www
,两个文件utils.py
的模块名分别是mycompany.utils
和mycompany.web.utils
。不能和Python自带的模块名称冲突。例如,系统自带了sys模块,自己的模块就不可命名为sys.py,否则将无法导入系统自带的sys模块。
二、使用模块
1.代码解释:
#!/usr/bin/env python3
"""该行是可以让这个hello.py文件直接在Unix/Linux/Mac上运行,
就像windows中的.exe文件"""
# -*- coding: utf-8 -*-
"""表示.py文件本身使用标准UTF-8编码"""
' a test module '
"""一个字符串,表示模块的文档注释,
任何模块代码的第一个字符串都被视为模块的文档注释"""
__author__ = 'Michael Liao'
"""使用__author__变量把作者写进去,
这样当你公开源代码后别人就可以瞻仰你的大名"""
import sys
"""
导入sys模块后,我们就有了变量sys指向该模块,
利用sys这 个变量,就可以访问sys模块的所有功能
"""
def test():
args = sys.argv
"""
导入sys模块后,我们就有了变量sys指向该模块,
利用sys这个变量,就可以访问sys模块的所有功能。
sys模块有一个argv变量,用list存储了命令行的所有参数。
argv至少有一个元素,因为第一个参数永远是该.py文件的名称,
例如:运行python3 hello.py获得的sys.argv就是['hello.py'];
运行python3 hello.py Michael获得的sys.argv就是
['hello.py', 'Michael]。
"""
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
"""
当我们在命令行运行hello模块文件时,
Python解释器把一个特殊变量__name__置为__main__,
而如果在其他地方导入该hello模块时,if判断将失败,
因此,这种if测试可以让一个模块通过命令行运行时执行
一些额外的代码,最常见的就是运行测试。
"""
test()
2.作用域:类似 "__name"变量和“__name__”一个是私有的,一个是特殊用途公开的。
正常的函数和变量名是公开的(public),可以被直接引用,比如:
abc
,x123
,PI
等;类似__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊变量,hello
模块定义的文档注释也可以用特殊变量__doc__
访问,我们自己的变量一般不要用这种变量名;类似_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc
,__abc
等;
一个例子:
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
"""
我们在模块里公开greeting()函数,
而把内部逻辑用private函数隐藏起来了,
这样,调用greeting()函数不用关心内部的private函数细节,
这也是一种非常有用的代码封装和抽象的方法,
即:外部不需要引用的函数全部定义成private,
只有外部需要引用的函数才定义为public。
"""
return
3.常用模块
在使用Python时,我们经常需要用到很多第三方库,例如,上面提到的Pillow,以及MySQL驱动程序,Web框架Flask,科学计算Numpy等。用pip一个一个安装费时费力,还需要考虑兼容性。我们推荐直接使用Anaconda,这是一个基于Python的数据处理和科学计算平台,它已经内置了许多非常有用的第三方库,我们装上Anaconda,就相当于把数十个第三方模块自动安装好了,非常简单易用。
可以从Anaconda官网下载GUI安装包,安装包有500~600M,所以需要耐心等待下载。网速慢的同学请移步国内镜像。下载后直接安装,Anaconda会把系统Path中的python指向自己自带的Python,并且,Anaconda安装的第三方模块会安装在Anaconda自己的路径下,不影响系统已安装的Python目录。
三、搜索模块路径——环境变量
1.Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys
模块的path
变量中:
>>> import sys
>>> sys.path
['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip',
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', ...,
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
2.如果我们要添加自己的搜索目录,有两种方法:
(1) 直接修改
sys.path
,添加要搜索的目录:
>>> import sys
>>> sys.path.append('/Users/michael/my_py_scripts')
(2)第二种方法是设置环境变量
PYTHONPATH
,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。
四、变量命名规范
模块名: 小写字母,单词之间用_分割 ad_stats.py
包名: 和模块名一样
类名: 单词首字母大写 AdStats ConfigUtil
全局变量名(类变量,在java中相当于static变量): 大写字母,单词之间用_分割 :NUMBER 、 COLOR_WRITE
普通变量: 小写字母,单词之间 用_分割 this_is_a_var
实例变量: 以_开头,其他和普通变量一样 _price 、 _instance_var
私有实例变量(外部访问会报错): 以__开头(2个下划线),其他和普通变量一样 :__private_var
专有变量: __开头,__结尾,一般为python的自有变量,不要以这种方式命名 :__doc__、 __class__
普通函数: 和普通变量一样: get_name() 、count_number() 、ad_stat()
私有函数(外部访问会报错): 以__开头(2个下划线),其他和普通函数一样 __get_name()
————————————————————————————————————————————————————————————————————
文件名 :全小写,可使用下划线
包 :应该是简短的、小写的名字。如果下划线可以改善可读性可以加入。如mypackage。
模块 :与包的规范同。如mymodule。
类 :总是使用首字母大写单词串。如MyClass。内部类可以使用额外的前导下划线。
函数&方法 :函数名应该为小写,可以用下划线风格单词以增加可读性。如:myfunction,my_example_function。
*注意*:混合大小写仅被允许用于这种风格已经占据优势的时候,以便保持向后兼容。
函数和方法的参数 :总使用“self”作为实例方法的第一个参数。总使用“cls”作为类方法的第一个参数。
如果一个函数的参数名称和保留的关键字冲突,通常使用一个后缀下划线好于使用缩写或奇怪的拼写。
全局变量 :对于from M import *导入语句,如果想阻止导入模块内的全局变量可以使用旧有的规范,在全局变量上加一个前导的下划线。
*注意*:应避免使用全局变量
变量 :变量名全部小写,由下划线连接各个单词。如color = WHITE,this_is_a_variable = 1
*注意*:
1.不论是类成员变量还是全局变量,均不使用 m 或 g 前缀。
2.私有类成员使用单一下划线前缀标识,多定义公开成员,少定义私有成员。
3.变量名不应带有类型信息,因为Python是动态类型语言。如 iValue、names_list、dict_obj 等都是不好的命名。
常量 :常量名所有字母大写,由下划线连接各个单词如MAX_OVERFLOW,TOTAL。
异常 :以“Error”作为后缀。
缩写 :命名应当尽量使用全拼写的单词,缩写的情况有如下两种:
1.常用的缩写,如XML、ID等,在命名时也应只大写首字母,如XmlParser。
2.命名中含有长单词,对某个单词进行缩写。这时应使用约定成俗的缩写方式。
例如:
function 缩写为 fn
text 缩写为 txt
object 缩写为 obj
count 缩写为 cnt
number 缩写为 num,等。
前导后缀下划线 :(1)一个前导下划线:表示非公有。 (2)一个后缀下划线:避免关键字冲突。
两个前导下划线:当命名一个类属性引起名称冲突时使用。
两个前导和后缀下划线:“魔”(有特殊用途)对象或者属性,例如__init__或者__file__。绝对不要创造这样的名字,而只是使用它们。
*注意*:关于下划线的使用存在一些争议。
Python 用下划线作为变量前缀和后缀指定特殊变量。
_xxx 不能用'from module import *'导入
__xxx__ 系统定义名字
__xxx 类中的私有变量名
核心风格:避免用下划线作为变量名的开始。