转 Python学习(七)
原文出处
作者:Wanglikai91
出处:http://www.cnblogs.com/wanglikai91/
七、模块:
我们可以通过编写函数来复用代码,同样我们可以通过模块来复用大量函数。有多重方法可以编写模块,但是最简单的方法是创建一个以.py为后缀的文件来包含需要复用的变量和函数。另一种方式是以编写python解释器的本地语言编写模块。例如C语言编写的模块被编译后可供运行于标准python解释器上的python代码使用。模块可以被其它程序导入以使用其提供的功能。这也是为什么我们可以使用python标准库。
我们先来看看如何使用标准库模块:
1
2
3
4
5
6
7
8
9
|
# Filename: using_sys.py import sys print ( 'The command line arguments are:' ) for i in sys.argv: print (i) print ( '\n\nThe PYTHONPATH is' , sys.path, '\n' ) |
输出:
C:\Users\Administrator>python D:\python\using_sys.py we are arguments
The command line arguments are:
D:\python\using_sys.py
we
are
arguments
The PYTHONPATH is ['D:\\python', 'C:\\Windows\\system32\\python32.zip', 'C:\\Pyt
hon32\\DLLs', 'C:\\Python32\\lib', 'C:\\Python32', 'C:\\Python32\\lib\\site-pack
ages']
首先我们使用import语句导入sys模块。本质上这告诉python我们希望使用这个模块。sys模块包含python解释器与其工作环境(即系统)相关的功能。
当python执行import sys语句时,它将查找sys模块。本例中sys是内建模块之一,因此python知道在哪能找到它。 如果导入的不是一个编译模块,即不是用python编写的模块,python解释器会在变量sys.path中列出的目录中查找它。 如果模块被找到,这个模块中的语句将被执行然后你就可以使用它了(注: 只有顶级语句才会执行,也就是主块中的语句)。
注意一个模块只有在第一次导入时会被初始化。
sys模块中的argv通过点号引用即sys.argv。它清晰的指出这个名字是sys模块中的一部分。这种语法的另一个优势是不会和你的程序中的同名argv变量发生冲突。 变量sys.argv是一个字符串列表(后章会详细解释列表)。具体说sys.argv是一个包含命令行参数的列表,也就是使用命令行传递给你的程序的参数。 如果你在使用IDE编写程序,请在菜单中查找为程序指定命令行参数的方法。
这里,当我们执行python using_sys.py we are arguments时,我们以python命令运行using_sys.py模块,其后的内容是传递给程序的参数。python将它们存到sys.argv以供我们使用。
注意:被运行脚本的脚本名永远是sys.argv的第一个参数。
所以本例中sys.argv[0]为’using_sys.py’,sys.argv[1]为’we’,sys.argv[2]是’are’, argv[3]是’arguments’。注意python下标从0开始而非1。 sys.path包含一个目录名列表指示从哪里导入模块。
1、字节编译的.pyc文件
输入一个模块相对来说是一个比较费时的事情,所以Python做了一些技巧,以便使输入模块更加快一些。一种方法是创建字节编译的文件,这些文件以.pyc作为扩展名。字节编译的文件与Python变换程序的中间状态有关。当你在下次从别的程序输入这个模块的时候,.pyc文件是十分有用的——它会快得多,因为一部分输入模块所需的处理已经完成了。另外,这些字节编译的文件也是与平台无关的。
注意:.pyc文件一般被创建在与其对应的.py文件所在的相同目录下。如果python没有这个目录的写权限,则.pyc文件不会被创建。
2、from ... import ...语句
如果你想要直接输入argv变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv语句。如果你想要输入所有sys模块使用的名字,那么你可以使用from sys import *语句。这对于所有模块都适用。一般说来,应该避免使用from..import而使用import语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from math import * n = input ( "Enter range:- " ) p = [ 2 , 3 ] count = 2 a = 5 while (count < n): b = 0 for i in range ( 2 , a): if (i < = sqrt(a)): if (a % i = = 0 ): #print a, "is not a prime" b = 1 else : pass if (b ! = 1 ): #print a, "is a prime" p = p + [a] count = count + 1 a = a + 2 print p |
3、模块的__name__属性
每个模块都有一个名字,并且通过模块中的某些语句可以得到这个模块名。在一些想要搞清模块是独立运行还是被导入的情况下,这会非常方便。如前所述当模块第一次被导入时模块中的代码会被执行。我们可以据此改变模块独立执行时的行为方式。这可以通过模块的__name__属性做到。
例如:
运行第二个Import语句前把文件复制一份到python目录下才可以正常运行
1
2
3
4
5
6
|
# Filename: using_name.py if __name__ = = '__main__' : print ( 'This program is being run by itself' ) else : print ( 'I am being imported from another module' ) |
输出:
C:\Users\Administrator>python D:\python\using_name.py
This program is being run by itself C:\Users\Administrator>python
Python 3.2.2 (default, Sep 4 2011, 09:51:08) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.>>> import using_name
I am being imported from another module
工作原理:
每个python模块都有自己的__name__定义,如果它是'__main__’则暗示模块为独立运行,我们可以进行一些适当的处理。
4、创建自己的模块
创建你自己的模块很简单,其实你一直在这样做!因为每个python脚本都是一个模块。你只需确保它带有.py扩展名即可。
下面的例子会让你对其有一个清晰的认识:
1
2
3
4
5
6
7
8
|
# Filename: mymodule.py def sayhi(): print ( 'Hi, this is mymodule speaking.' ) __version__ = '0.1' # End of mymodule.py |
上面就是一个简单的模块,如你所见,这和我们平时的python程序相比没有什么特别之处。
记住模块应该放到导入它的那个程序所在的目录下,或者放到sys.path列出的目录之一中。
1
2
3
4
5
6
|
# Filename: mymodule_demo.py import mymodule mymodule.sayhi() print ( 'Version' , mymodule.__version__) |
输出:
C:\Users\Administrator>python D:\python\mymodule_demo.py
Hi, this is mymodule speaking.
Version 0.1
注意我们同样使用点号访问模块成员。python很好的重复利用了相同的符号,带来独特的’Pythonic’感受,这样我们就不必学习更多的语法知识了。
下面是一个使用from..import
语法的版本:
1
2
3
4
5
6
|
# Filename: mymodule_demo2.py from mymodule import sayhi, __version__ sayhi() print ( 'Version' , __version__) |
mymodule_demo2.py
的输出与mymodule_demo.py
完全相同。
注意,如果导入mymodule的模块中已经存在同名的__version__,则将发生名字冲突。其实上这很可能发生,因为每个模块都用__version__声明它的版本是一种常见的做法。因此建议你优先考虑import语句,虽然它可能会让你的程序变的更长一些。
你同样可以使用:from mymodule import *,这将导入模块的所有公有名字,例如sayhi,但是不会导入__version__因为它以双下划线开头。
5、dir()函数
你可以使用dir函数列出一个对象定义的所有标识符。例如对于一个模块,标识符包括函数,类,变量。当你为dir()函数提供一个模块名,它将返回定义在其中的所有名字。当dir()的参数为空时,返回定义在当前模块中所有名字。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
C:\Users\Administrator>python Python 3.2 . 2 (default, Sep 4 2011 , 09 : 51 : 08 ) [MSC v. 1500 32 bit (Intel)] on win 32 Type "help" , "copyright" , "credits" or "license" for more information. >>> dir (sys) [ '__displayhook__' , '__doc__' , '__excepthook__' , '__name__' , '__package__' , '__s tderr__ ', ' __stdin__ ', ' __stdout__ ', ' _clear_type_cache ', ' _compact_freelists', '_current_frames' , '_getframe' , 'api_version' , 'argv' , 'builtin_module_names' , ' byteorder ', ' call_tracing ', ' callstats ', ' copyright ', ' displayhook ', ' dllhandle' , 'dont_write_bytecode' , 'exc_info' , 'excepthook' , 'exec_prefix' , 'executable' , 'exit' , 'flags' , 'float_info' , 'getcheckinterval' , 'getdefaultencoding' , 'getfil esystemencoding ', ' getprofile ', ' getrecursionlimit ', ' getrefcount ', ' getsizeof', 'gettrace' , 'getwindowsversion' , 'hexversion' , 'intern' , 'maxsize' , 'maxunicode ', ' meta_path ', ' modules ', ' path ', ' path_hooks ', ' path_importer_cache ', ' platfor m ', ' prefix ', ' ps1 ', ' ps2 ', ' setcheckinterval ', ' setprofile ', ' setrecursionlimit ', ' settrace ', ' stderr ', ' stdin ', ' stdout ', ' subversion ', ' version ', ' version_in fo ', ' warnoptions ', ' winver'] >>> dir () # get list of attributes for current module [ '__builtins__' , '__doc__' , '__name__' , '__package__' , 'sys' ] >>> a = 5 # create a new variable 'a' >>> dir () [ '__builtins__' , '__doc__' , '__name__' , '__package__' , 'a' , 'sys' ] >>> del a # delete/remove a name >>> dir () [ '__builtins__' , '__doc__' , '__name__' , '__package__' , 'sys' ] |
工作原理:
首先,我们通过被导入的sys模块应用dir函数. 可以看到sys包含巨多的属性。
接下来,我们不为dir函数提供参数。默认的它返回当前模块的属性列表。注意被导入模块列表也是当前模块列表的一部分。
为了观察到dir确定起作用了,我们定义一个新变量a并为其赋值然后检验dir的返回值,我们发现在返回的列表中确实出现了一个与变量a同名的值。在我们使用del语句删除当前模块的变量/属性后,改变再次反映到了dir函数的输出上。
del注解 – 这个语句用于删除一个变量/名字,在本例中,del a之后你就无法访问变量a了 – 就像它从来没有存在过一样。
注意dir()函数可用于任何对象。例如执行dir (print)学习更多关于print函数的属性,或是dir(str)列出str类的属性。
6、包(Packages)
现在,你必须开始留心组织你的程序层次了。
变量在函数内部,函数和全局变量通常在模块内部。那么如何组织模块呢?这就轮到包登场了。包仅仅是包含模块的文件夹,并带有一个特殊的文件__init__.py用于指示python这个文件夹是特殊的,因为它包含python模块。让我们假设你需要创建一个叫做’world’的包,里面包括诸如’asia’,‘africa’等的子包。
下面告诉你应该如何组织文件夹结构:
- <some folder present in the sys.path>/ - world/ - __init__.py - asia/ - __init__.py - india/ - __init__.py - foo.py - africa/ - __init__.py - madagascar/ - __init__.py - bar.py
包只是用来有层次的组织模块。你会在标准库中看到它的很多应用。