模块让你能够有逻辑地组织你的Python代码段。
把相关的代码分配到一个 模块里能让你的代码更好用,更易懂。
模块也是Python对象,具有随机的名字属性用来绑定或引用。
简单地说,模块就是一个保存了Python代码的文件。模块能定义函数,类和变量。模块里也能包含可执行的代码。
Sam学习Python的过程,主要是跟着《Learn PYTHON the Hard WAY》,其中习题40中,明确指出,
A: 模块是包含函数和编来那个的Python文件。
B: 其它程序可以导入这个文件。
C: 然后可以使用 . 操作符访问模块中的函数和变量。
例1:
supports.py:
def apple():
print "I am an Apple!"
tangerine = "Living reflection of a dream"
接下来就可以import这个模块,并用 .操作符调用函数。
import supports
supports.apple()
print supports.tangerine
1. 模块的导入:
模块的导入方式有以下几种:
A: import
B: from .... import
C: from .... import *
导入模式的异同:
A:import:
import supports
supports.apple()
print supports.tangerine
在调用函数,变量和类时,需要使用模块名+.操作符调用。
B:from ModuleName import name
from语句让你从模块中导入一个指定的部分到当前命名空间中.
from supports import apple
这个声明不会把整个supports模块导入到当前的命名空间中,它只会将supports里的apple单个引入到执行这个声明的模块的全局符号表。
C: from ModuleName import *
把一个模块的所有内容全都导入到当前的命名空间也是可行的
B和C连个方式,在使用函数,变量和类时,不需要使用模块名+.操作符调用。 而是直接调用。
例如:
from supports import *
apple()
print tangerine
2. 模块定位:
当使用import ,from... import...导入模块时, Python解析器对模块定位的搜索顺序为:
1. 当前目录。 (即input script所在目录)
2. shell 变量 PYTHONPATH下的每个目录。
3. 默认目录。Python安装目录。 如: /usr/local/lib/python
截至到现在,Python module还是很清晰的。Python由 modulename.py构成。内容放置在modulename.py中。modulename就是文件名。
文件名就是模块名加上后缀.py
导入方式有三种。看来没啥问题。
3. 模块导入的具体行为:
一个模块被导入,那些内容被执行,哪些不被执行呢?这就是模块导入的具体行为定义的:
每个module都包含对象定义和一些语句(statements),这些语句应该是意图要来初始化这个module的,这些语句会在这个module第一次被import的时候执行(多次import只会执行一次,不管是以上两种import的语句中那一种),当这个module被作为一个script来运行的时候也会被执行。
每个module都有自己的private symbol table,当使用第一种import语句import一个module的时候,引入者的local symbol table就加入了这个module,其名字如果没有使用as的话就是被引入的模块名本身。使用第二种import语句这会在引入者的local symbol table中加入具体引用的item,其名称若没使用as则就为item的名称。
这就是为何单纯import时,需要用modulename.item. 而是用from...import时, 直接调用item本身。
例:
fibo.py如下:
1 print ("__name__ :", __name__) 2 def fib(n): 3 a, b = 0, 1 4 result = [] 5 print ("in fib():", __name__) 6 while (b<<span style="font-family: 'Courier New' !important;">n): 7 result.append(b) 8 a, b = b, a+b 9 print(result)
这个fibo.py就是一个module,它有一个函数定义fib(),和一个语句(statement),第一行的print语句,我们在当前文件目录运行Python Interpreter就可以去引入这个模块,并执行模块中定义的fib()函数。
>>> import fibo ('__name__ :', 'fibo') #print语句执行 >>> fibo.fib(10) ('in fib() :', 'fibo') #fib()函数执行 [1, 1, 2, 3, 5, 8]
可以看到,在import的时候,这个module的语句(statements)执行了,所定义的函数并未执行,在通过module名引用module中的函数定义时,函数才被执行。
同样可以在一个script file中引入module,我们在fibo.py所在的目录创建另一个文件calculat.py
1 from fibo import fib 2 for n in range(10, 50, 5): 3 fib(n)
然后用Python解释器运行calcute.py得到结果。
4. Python标准库:
Python有一个标准库,其中定义了一系列的module,这些module中的一部分是直接集成在Interpreter中的,这些built-in module主要提供了很重要的但是Python语言又没有提供的功能,比如跟system call有关的sys module就集成在所有平台的Python Interpreter中,在Interpreter中集成哪些module是可以配置的,并且随平台不同而有差别。
遇到问题:
Sam在看一些例子代码时,首先遇到了:
import serial
import socket
等语句。
那按照以上认识,就应该有serial.py, socket.py等module存在。但Sam在当前目录,PYTHONPATH,/usr/local/lib/python等目录下均未能发现。这就有了疑问。
在疑问研究中,看到如下用法:
#pry
>>>import serial
>>>print serial.__file__
/usr/lib/python2.7/dist-packages/serial/__init__.pyc
>>>import socket
>>>print socket.__file__
/usr/lib/python2.7/socket.pyc
(__file__指向该模块的导入文件名)
Sam由此想到,是否除了 *.py, 还有类似 *.pyc的模块名呢?但__init__.py又是什么鬼?这就牵涉出Python中另一个概念---Pakcage。
5. python中的Package:
Package是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的Python的应用环境。
package是一个directory,它包含sub-package或者是module,而module是.py文件,要让Python Interpreter把一个目录作为package,则该目录下必须有__init__.py文件,__init__.py可以为空,当然也可以有对象定义和语句,用来做初始化工作,__init__.py还有个作用就是设置__all__变量。
package本身就可以来作为一个module使用,只是它所包含的sub-module或module可以通过package name用package.module的名称形式去引用,这更有利于组织一系列相关的module,避免module间定义的名称的混乱。
package在实际工程中非常常用,__init__.py也常常不会为空,而会有对象定义和初始化代码来让这个包,也就是这个module,包含其该有的item定义。以后我们会对package做更多了解。
考虑一个在Phone目录下的pots.py文件。这个文件有如下源代码:
#!/usr/bin/python # -*- coding: UTF-8 -*- def Pots(): print "I'm Pots Phone"
同样地,我们有另外两个保存了不同函数的文件:
- Phone/Isdn.py 含有函数Isdn()
- Phone/G3.py 含有函数G3()
现在,在Phone目录下创建file __init__.py:
- Phone/__init__.py
当你导入Phone时,为了能够使用所有函数,你需要在__init__.py里使用显式的导入语句,如下:
from Pots import Pots from Isdn import Isdn from G3 import G3
当你把这些代码添加到__init__.py之后,导入Phone包的时候这些类就全都是可用的了。
#!/usr/bin/python # -*- coding: UTF-8 -*- # 导入 Phone 包 import Phone Phone.Pots() Phone.Isdn() Phone.G3()
以上实例输出结果:
I'm Pots Phone I'm 3G Phone I'm ISDN Phone
如上,为了举例,我们只在每个文件里放置了一个函数,但其实你可以放置许多函数。你也可以在这些文件里定义Python的类,然后为这些类建一个包。
通过学习Pakcage,就可以完全解释:/usr/lib/python2.7/dist-packages/serial/__init__.pyc
即serial是一个pakcage.
具体举例分析:
port_publisher.py:
import os
import select
import socket
import sys
import time
import traceback
import serial
import serial.rfc2217
import slerialtools.list_ports
import dbus
其中,serial 就是一个Package. 在serial目录内,包含有__init__.py.
/