模块
前面有简单介绍如何使用import从外部模块获取函数并且为自己的程序所用:
>>> import math
>>> math.sin(0) #sin为正弦函数
0.0
模块是程序
任何python程序都可以作为模块导入。假设写如下程序,并且将它保存为以C:\python\hello.py
#hello.py
print "hello,world!"
下面通过python解释器调用:
>>> import sys
>>> sys.path.append('c:/python')
>>> import hello
hello,world!
再来一次:
>>> import hello
>>>
怎么这次没结果?因为导入模块并不意味着在导入进执行某些操作。它们主要用于定义,比如变量、函数和类等。此外,因为只需要定义这些东西一次,导入模块多次和导入一次的效果是一样的。
模块用于定义
1、在模块中定义函数
假设我们编写了一个类似代码的模块,将其保存为hello2.py 文件。
#hello2.py
def hello():
print "hello, world !"
保存后,可以像下面这样导入:
>>> import hello2
模块会被执行,这意味着hello函数在模块的作用被定义了。因此可以通过以下方式来访问函数:
>>> hello2.hello()
hello.world!
2、在模块中增加测试代码
模块用来定义函数、类和其他内容,有时候在模块中添加一些检查模块本身是否正常工作的测试代码是非常有用的。
#hello3.py
def hello():
print "hello.world!"
def test():
hello()
if __name__ == '__main__': test()
f __name__ == '__nain__' 解释:
python文件的后缀为.py ,.py文件可以用来直接运行,就像一个独立的小程序;也可以用来作为模块被其它程序调用。
__name__是模块的内置属性,如果等于'__main__' 侧表示直接被使用,那么将执行方法test()方法;如果是被调用则不执行 if 判断后面的test()方法。
执行结果:
>>> import hello3 #表示hello3模块被调用,不执行test方法,所以没有输出
>>> hello3.hello() #表示程序执行,调用test方法
hello.world!
>>> hello3.hello() #这里是不是可以反复调用test方法
hello.world!
让模块可用
前面的例子中,我们改变了sys.path,其中包含了一个目录列表,解释器在该列表中查找模块。在理想情况下,一开始sys.path本身就应该包含正确的目录,有两方法可以做到这一点: 一是将模块放置在合适的位置,别外一种是告诉解释器去哪里查找需要的模块。
1、将模块放置在正确的位置
来看看python解释器会从哪里查找模块
>>> import sys,pprint
>>> pprint.pprint(sys.path)
['',
'I:\\Python27\\Lib\\idlelib',
'C:\\Windows\\system32\\python27.zip',
'I:\\Python27\\DLLs',
'I:\\Python27\\lib',
'I:\\Python27\\lib\\plat-win',
'I:\\Python27\\lib\\lib-tk',
'I:\\Python27',
'I:\\Python27\\lib\\site-packages',
'c:/python']
尽管这些目录下都可以被找到,但site-packages 目录是最佳选择。
2、告诉编译器去哪里找
以下情况是告诉编译器去哪儿找的原因:
** 不希望将自己的模块填满python解释器的目录
** 没有在python解释器目录中存储文件的权限
** 想将模块放到其它位置
编辑sys.path ,前面就已经使用了
>>> import sys
>>> sys.path.append('c:/python')
但更优雅的做法是配置pythonpath环境变量,方法和配置java 环境变量类似。
文档
模块信息的自然来源是文档,除了通过python书籍或标准python文档来查看某个函数的含义,也可以通过下面方式:
>>> print range.__doc__
range([start,] stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
这样就获得了关于range函数的精确描述。
time 模块
time模块所包括的函数能够实现 以下功能:获得当前时间,操作时间和日期,从字符串读取时间以及格式化时间为字符串。
time模块中重要的函数
time.asctime将当前时间格式化为字符串:
>>> time.asctime()
'Thu May 16 00:00:08 2013'
random模块
random模块包括返回随机的函数,可以用于模拟或者用于任何产生随机输出的程序。
random模块中的一些重要函数:
下面介绍使用random模块的例子,还需要用到time模块中的函数。
例1:首先获得代表时间间隔(2013年)限制的实数,这可以通过时间元组的方式来表示日期(使用 -1表示一周的某天,一年中某天和夏令时,以例让python自己计算),并且对这些元组调用mktime :
from random import *
from time import *
data1 = (2013 ,1,1,0,0,0,-1,-1,-1)
time1 = mktime(data1)
data2 = (2014 ,1,1,0,0,0,-1,-1,-1)
time2 = mktime(data2)
#然后在这个范围内生成随机数
>>> random_time = uniform(time1,time2)
# 可以将数字转换成易读的日期形式
>>> print asctime(localtime(random_time))
Fri Jan 18 18:23:16 2013
例2:下面一个例子,假设三个人打牌,首先要保证54张牌没有重复的,第人发手里18张(斗地主就不能平均分配了)。
>>> values = range(1,13) + 'dwang xwang'.split() #定义13个数字与大小王
>>> suits = 'hei hong mei fang '.split() # 定义牌的四种类型(黑、红、梅、方)
>>> deck = ['%s of %s' %(v ,s ) for v in values for s in suits] #循环嵌套将其循环组合
>>> from pprint import pprint #调用pprint 模块
>>> pprint (deck [:18]) #输出18张牌
['1 of hei',
'1 of hong',
'1 of mei',
'1 of fang',
'2 of hei',
'2 of hong',
'2 of mei',
'2 of fang',
'3 of hei',
'3 of hong',
'3 of mei',
'3 of fang',
'4 of hei',
'4 of hong',
'4 of mei',
'4 of fang',
'5 of hei',
'5 of hong']
#显然上面的输出太整齐,调用随机函数,随机一点
>>> from random import shuffle
>>> shuffle(deck)
>>> pprint(deck[:18])
['5 of fang',
'6 of hong',
'5 of mei',
'dwang of fang',
'xwang of fang',
'10 of hong',
'7 of mei',
'12 of hong',
'6 of hei',
'12 of hei',
'7 of hei',
'8 of hei',
'4 of fang',
'dwang of hei',
'11 of hei',
'12 of fang',
'5 of hei',
'2 of hong']
不过,依然是有问题的,大小王不应该分类型(黑、红、梅、方),显然上面的结果不够完美。