《Python基础教程》要点(十):充电时刻:导入模块

时间:2021-01-29 18:43:34

Python的标准安装包括一组模块,称为标准库

一、导入模块

第一种方法

1、有模块放在D:/python/py

#D:/python/py/hello.py

print "Hello !"

在主程序想用该模块:

>>> import hello

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import hello
ImportError: No module named hello



>>> import sys
>>> sys.path.append('D:/python/py')
>>> import hello
Hello !

告诉解释器:除了从默认的目录中寻找之外,还需要从目录D:/python/py中寻找。

可见,导入模块的时候,其中的代码被执行了。

再次导入,却不发生了:

>>> import hello
>>> 

“只导入一次”。在两个模块相互导入的情况中很重要。

如果坚持重新载入模块,那么可以使用内建的reload函数

模块真正的用处在于它们(像类一样)可以保持自己的作用域。

2、在模块中定义函数:

如果模块hello2.py里定义了函数如:def say():print 'hello !'那么import hello2 后,模块hello2会被执行,其函数say在hello2模块的作用域内被定义了。可以这样访问模块里的函数:hello2.say()。

#D:/python/py/hello2.py

def sayhello():
    print "Hello !"

在主程序(另启动所以再找目录):

>>> import sys
>>> sys.path.append('D:/python/py')
>>> import hello2
>>> hello2.sayhello()
Hello !

3、在模块中增加测试代码:

关键:告知模块本身是作为程序运行还是导入到其他程序。使用__name__变量

__name__变量,在主函数中的值是'__main__',而在导入的模块中,这个值就被设定为模块的名字。因而可以通过该值 把握 模块正在主程序中执行时该怎么做。

#D:/python/py/hello2.py

def hello():
    print "can you see me ? "

def test():

    hello()

if
__name__ == '__main__':test()

在主程序:

>>> import hello2
>>> hello2.test()
can you see me ? 

想测试哪些函数就把哪些函数放在test()函数下,在主程序里模块名.test()即可测试。

第二种方法:

让sys.path本身就包含正确的目录(除默认目录,还有你自己放py文件的目录)。

将模块放在正确位置:

找出Python解释器从哪里查找模块,然后将你自己的文件放置在那里即可。

搜索路径:

>>> import sys,pprint
>>> pprint.pprint(sys.path)
['C:\\Python27\\Lib\\idlelib',
 'C:\\Windows\\system32\\python27.zip',
 'C:\\Python27\\DLLs',
 'C:\\Python27\\lib',
 'C:\\Python27\\lib\\plat-win',
 'C:\\Python27\\lib\\lib-tk',
 'C:\\Python27',
 'C:\\Python27\\lib\\site-packages']
>>> 

pprint是个相当好的打印函数。
site-packages目录是最佳选择,因为它就是用来做这些事情的。

第三种方法:

告诉编译器去哪里找。

除方法一外,可以在PYTHONPATH环境变量中包含模块所在的目录。

 二、包。

为了组织好模块,将它们分组为

包就是另外一类模块。

包能包含其他模块。

为了让python将其作为包对待,它必须包含一个命名为__init__.py的文件(模块)。

一个(普通)模块(存储在文件中,扩展名.py,比如hello2.py)所在的“目录”就是包(#D:/python/pyfile/hello2.py则 pyfile 就是)。

也可以将hello2.py看成

pyfile也是另一类模块

将一个模块(如pyfile)作为 普通模块 导入,该(pyfile)文件的内容就是包的内容。比如有个名为consants的包,文件constants/__init__py包括语句PI=3.14,那么可以:

import constants
print constants.PI

想将模块放置在包内,直接将模块放在包目录内即可。

如过建立一个包drawing,包括shapes和clolors模块,当然,也有__init__.py模块,可以这样:

文件目录:

-/python/        (PYTHONPATH中的目录)

-/python/drawing/__init__.py

-/python/drawing/clolors.py

-/python/drawing/shapes.py

import drawing      #此时drawing中的__init__模块内容可用。另两个模块不用。
import drawing.colors   #colors模块可用,但是只能通过全名drawing.colors。
from drawing import shapes   #可以直接用shapes这个短名。

 

三、探究模块。


1、查看模块包含的内容可以使用 dir 函数

>>> import copy
>>> dir(copy)
['Error', 'PyStringMap', '_EmptyClass', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_copy_dispatch', '_copy_immutable', '_copy_inst', '_copy_with_constructor', '_copy_with_copy_method', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_inst', '_deepcopy_list', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', '_test', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']
>>> 

以下划线开始的名字--暗示它们并不是为在模块外部使用而准备的。可以过滤掉它们好看点:

>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'PyStringMap', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']

 2、__all__变量

这个变量包含一个列表。

>>> copy.__all__
['Error', 'copy', 'deepcopy']

它定义了模块的公有接口(public interface),告诉解释器:从模块导入“所有名字”(即*)代表什么含义:

>>> from copy import*

这样导入只能使用__all__中的4个函数。想导入其他函数,要显示地实现。

3、用 help 获取帮助。

>>> import copy
>>> from copy import*
>>> help(copy)
Help on function copy in module copy:

copy(x)
    Shallow copy operation on arbitrary Python objects.
    
    See the module's __doc__ string for more info.

告诉你copy带个参数x,而且是潜复制。

模块也可有文档字符串(写在模块开头)。类也一样。

事实上,上面的帮助文本是从copy函数的文档字符串中取出的

>>> print copy.__doc__
Shallow copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.

使用help 与 直接检测文档字符串 相比,help能获取更多信息,比如函数签名(所带参数)。

试着用help(copy)(对模块本身,而不是其函数):

>>> import copy
>>> help(copy)

会看到很多信息,包括copy和deepcopy之间区别的透切讨论。

 4、文档。

学习python编程最有用的文档莫过于Python库参考。

5、使用源代码

想阅读标准模块copy的源码,找的方法有:

1)检查sys.path,然后自己找。就行解释器做的一样。

2)检查模块的__file__属性

>>> print copy.__file__
C:\Python27\lib\copy.pyc

【注意】如果文件以.pyc结尾,只要查看相应的以.py结尾的文件即可。
【注意】一些模块并不包含任何可以阅读的Python源代码。它们可能已经融入到解释器内了(比如sys模块),或者可能是使用c程序语言写成的(c语言扩展python信息查看17章)。

四、标准库:一些最爱

1、sys

2、os

os模块为你提供了访问多个操作服务系统的功能。

例如其函数system(command),在子shell中执行操作系统命令。

打开浏览器:

>>> import os
>>> os.startfile(r'C:\Program Files\Google\Chrome\Application\chrome.exe')
>>> import os
>>> os.system(r'C:\Program Files\Google\Chrome\Application\chrome.exe')
1
>>> os.system(r'C:\"Program Files"\Google\"Chrome"\Application\chrome.exe')
0
>>> #以上代码并不是完美的解决方法。另外可用Windows特有的函数--os.startfile,它接受一般路径,就算包含空格也没问题。
>>> os.startfile(r'C:\Program Files\Google\Chrome\Application\chrome.exe')

 【注意】在Windows中,由os.system(或者os.startfile)启动了外部程序之后,Python程序仍然会继续运行。而在UNIX中,程序会中止,等待os.system命令完成。

更好的解决方案:WEBBROWSER

打开Python的网站:

>>> import webbrowser
>>> webbrowser.open('http://www.python.org')
True

网页就弹出来了。

 

3、fileinput

五、集合、堆和双端队列

1、集合。

2、堆。

堆是优先队列的一种。(位于 i 位置上的元素总比 i//2 位置处的元素大--堆属性)

其函数

heappop(heap)弹出最小的函数--一般来说总是索引0处的元素。

>>> from heapq import *
>>> from random import shuffle
>>> data = range(10)
>>> shuffle(data)
>>> heap = []
>>> for n in data:
    heappush(heap,n)

    
>>> heap
[0, 1, 4, 2, 7, 9, 6, 3, 5, 8]
>>> heappush(heap,0.5)
>>> heap
[0, 0.5, 4, 2, 1, 9, 6, 3, 5, 8, 7]
>>> heappop(heap)
0
>>> heappop(heap)
0.5
>>> heap
[1, 2, 4, 3, 7, 9, 6, 8, 5]
>>> 

heapify函数使用任意列表作为参数,将列表转换为合法的堆。如果没有用heappush建立堆,那么在使用heappush和heappop前应该使用这个函数。

>>> heap = [5,8,0,3,2,7,9,1,4,2]
>>> heapify(heap)
>>> heap
[0, 1, 5, 3, 2, 7, 9, 8, 4, 2]
>>> 

3、双端队列。 

六、time

 time模块功能:获取当前时间、操作时间和日期、从字符串读取时间以及格式化时间为字符串。

其详细函数参考Python库参考的14.2节。

如asctime([tuple])将时间元组转换为字符串

>>> import time
>>> time.asctime()             #将当前时间格式化为字符串
'Sat Jul 06 22:32:16 2013'

 七、random

 其函数

random.random是最基本的随机函数之一,它只是返回0-1 之间的伪随机数。

random.getrandbits以长整型形式返回给定的位数(二进制数)。如果处理的是真正的随机事物(比如加密),这个函数尤为有用。

 

>>> from random import *
>>> random()
0.1475392989955424
>>> random()
0.2747578891375263
>>> getrandbits(2)
0L
>>> getrandbits(2)
1L
>>> #产生1-10随机数:
>>> randrange(1,11)
10
>>> randrange(10)+1
1
>>> #获得小于20的随机正奇数
>>> randrange(1,20,2)
11
>>> 

 发牌游戏:洗牌并且每按一次回车就发一次牌。

 

>>> values = range(1,11)+'J Q K'.split()
>>> values
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
>>> suits = 'a b c d'.split()
>>> suits
['a', 'b', 'c', 'd']
>>> deck = ['%s of %s' % (v,s) for v in values for s in suits]
>>> deck
['1 of a', '1 of b', '1 of c', '1 of d', '2 of a', '2 of b', '2 of c', '2 of d', '3 of a', '3 of b', '3 of c', '3 of d', '4 of a', '4 of b', '4 of c', '4 of d', '5 of a', '5 of b', '5 of c', '5 of d', '6 of a', '6 of b', '6 of c', '6 of d', '7 of a', '7 of b', '7 of c', '7 of d', '8 of a', '8 of b', '8 of c', '8 of d', '9 of a', '9 of b', '9 of c', '9 of d', '10 of a', '10 of b', '10 of c', '10 of d', 'J of a', 'J of b', 'J of c', 'J of d', 'Q of a', 'Q of b', 'Q of c', 'Q of d', 'K of a', 'K of b', 'K of c', 'K of d']
>>> from random import shuffle
>>> shuffle(deck)
>>> from pprint import pprint
>>> pprint(deck)
['9 of d',
 'Q of d',
 '1 of c',
 'Q of b',
 'K of d',
 '4 of b',
 '8 of b',
>>> while deck:raw_input(deck.pop())

J of c
''
2 of d
''
K of b
''

 《Python基础教程》要点(十):充电时刻:导入模块