类的概念在许多语言中出现,很容易理解。它将数据和操作进行封装,以便将来的复用

模块

模块,在Python可理解为对应于一个文件。在创建了一个脚本文件后,定义了某些函数和变量。你在其他需要这些功能的文件中,导入这模块,就可重用这些函数和变量。一般用module_name.fun_name,和module_name.var_name进行使用。这样的语义用法使模块看起来很像类或者名字空间,可将module_name 理解为名字限定符。模块名就是文件名去掉.py后缀

模块搜索路径

当导入一个模块时,解释器先在当前包中查找模块,若找不到,然后在内置的built-in模块中查找,找不到则按sys.path给定的路径找对应的模块文件(模块名.py)

  • sys.path的初始值来自于以下地方:

    • 包含脚本当前的路径,当前路径
    • PYTHONPATH
    • 默认安装路径
  • sys.path初始化完成之后可以更改

    • 编译过的Python文件: .pyc文件
    • built-in 模块

上面的例子中,当client被导入后,python解释器就在当前目录下寻找client.py的文件,然后再从环境变量PYTHONPATH寻找,如果这环境变量没有设定,也不要紧,解释器还会在安装预先设定的的一些目录寻找。这就是在导入下面这些标准模块,一切美好事情能发生的原因。

这些搜索目录可在运行时动态改变,比如将module1.py不放在当前目录,而放在一个冷僻的角落里。这里你就需要通过某种途径,如sys.path,来告知Python了。sys.path返回的是模块搜索列表,通过前后的输出对比和代码,应能理悟到如何增加新路径的方法了吧。非常简单,就是使用list的append()或insert()增加新的目录。

  1. #module2.py
  2. import sys
  3. import os
  4. print sys.path
  5. workpath = os.path.dirname(os.path.abspath(sys.argv[0]))
  6. sys.path.insert(0, os.path.join(workpath, 'modules'))
  7. print sys.path

其他的要点

模块能像包含函数定义一样,可包含一些可执行语句。这些可执行语句通常用来进行模块的初始化工作。这些语句只在模块第一次被导入时被执行。这非常重要,有些人以为这些语句会多次导入多次执行,其实不然。

模块在被导入执行时,python解释器为加快程序的启动速度,会在与模块文件同一目录下生成.pyc文件。我们知道python是解释性的脚本语言,而.pyc是经过编译后的字节码,这一工作会自动完成,而无需程序员手动执行

通常包总是一个目录,可以使用import导入包,或者from + import来导入包中的部分模块。包目录下为首的一个文件便是 __init__.py

  • 可以从包中导入单独的模块。
    • import PackageA.SubPackageA.ModuleA,使用时必须用全路径名
    • from PackageA.SubPackageA import ModuleA, 可以直接使用模块名而不用加上包前缀。
    • from PackageA.SubPackageA.ModuleA import,可以直接导入模块中的函数或变量

通俗一点:包是一个包含init.py 文件的目录,该目录下一定得有这个init.py文件和其它模块或子包

  1. package_a
  2. ├── __init__.py
  3. ├── module_a1.py
  4. └── module_a2.py
  5. package_b
  6. ├── __init__.py
  7. ├── module_b1.py
  8. └── module_b2.py
  9. main.py
  • 如果packagea中的modulea1需要引用packageb,那么默认情况下,python是找不到packageb。我们可以使用sys.path.append('../'),可以在packagea中的init.py添加这句话,然后该包下得所有module都添加* import _init即可

常见问题:

  • 引入某一特定路径下的模块
    • 使用sys.path.append(yourmodulepath)
  • 将一个路径加入到python系统路径下,避免每次通过代码指定路径
  • 利用系统环境变量 export PYTHONPATH=$PYTHONPATH:yourmodulepath
  • 直接将这个路径链接到类似/Library/Python/2.7/site-packages目录下

好的建议

  • 经常使用if name == ‘main’,保证你写包既可以import又可以独立运行,用于test。
  • 多次import不会多次执行模块,只会执行一次。可以使用reload来强制运行模块,但不提倡