这一部分是Python方面的一些学习笔记,用于记录自己学习Python的过程,同时也是对自己Python这块知识的一个梳理,后期也可用于Python复习。
Python学习的第三篇,介绍Python常见模块的用法,其中包括os模块、matplotlab模块等。
Python的系统模块包括sys, os, glob, socket, threading, _thread, queue, time, timeit, subprocess, multiprocessing, signal, select, shutil, tempfile等。大多数系统级接口集中在:sys和os两个模块。
sys模块
sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:Python解释器。与os模块相比,其更多的在于针对系统环境的交互,而os则操作文件目录。
导入sys模块
首先,打开终端模拟器进入Python解释器或者打开IDE编辑器创建一个新的.py后缀名的Python程序文件。
下面,以解释器中的操作举例:
`
注意:如果是在编辑器,一定要注意要事先声明代码的编码方式,否则中文会乱码。
sys模块常见函数
sys.argv
: 命令行参数,包括脚本名称,实现从程序外部向程序传递参数
sys.exit([arg])
: 程序中间的退出,arg=0为正常退出
sys.path
: 查找模块所在目录的目录名列表
sys.modules
:映射模块名字到载入模块的字典
sys.platform
: 获取当前系统平台
sys.stdin
:标准输入流-一个类文件(file-like)对象
sys.stdout
:标准输出流-一个类文件对象
sys.stderr
:标准错误流-一个类文件对象
sys.getdefaultencoding()
: 获取系统当前编码,一般默认为ascii。
sys.setdefaultencoding()
: 设置系统默认编码,需要reload(sys)才能查询看到
sys.getfilesystemencoding()
: 获取文件系统使用编码方式,Windows下返回’mbcs’,mac下返回’utf-8’
sys模块常见函数
sys.argv
sys.argv
是命令行参数,包括脚本名称,它的功能可以实现从程序外部向程序传递参数。那么这个过程是如何实现的呢?假设有一个名为test.py
的文件,则可以通过import sys
和print sys.argv[number]
两句来实现。number=0为这个脚本的名字,1,2,…则为命令行下传递的参数。
如test.py脚本内容如下:
1
2
3
4
5
6
|
import sys
print sys.argv[
0]
print sys.argv[
1]
print sys.argv[
2]
print sys.argv[
3]
|
那么要实现参数传递即可采用>>>python test.py arg1 arg2 arg3
实现。下文会结合sys.path
给出一个示例。上述命令的输出结果为:
1
2
3
4
|
test.py
arg1
arg2
arg3
|
sys.exit([arg])
执行至主程序的末尾时,解释器会自动退出。但如果需要中途退出程序,可以调用sys.exit()
函数来实现。它带有一个可选的整数参数返回给调用它的程序。这意味着你可以在主程序中捕获对sys.exit()
的调用。(0为正常退出,其他为不正常,可抛异常事件供捕获)
sys.exit()
函数运行示例如下:
1
2
3
4
5
6
7
8
|
import sys
print
"hello"
try:
sys.exit(
1)
except SystemExit:
pass
print
"there"
|
输出结果为:
还可以获取发生的异常类型(需要进入异常处理进程),如以下示例:
1
2
3
4
5
6
7
8
9
10
|
def (value):
print value
sys.exit(
0)
print
'Hello'
try:
sys.exit(
1)
except SystemExit,value:
exitfunc(value)
print
'end'
|
上述代码输出结果见下:
1
2
3
4
5
|
Hello
1
An exception has occurred, use %tb to see the full trackback.
SystemExit:
0
|
执行%tb
命令后发现其追踪了sys.exit(0)
这句异常,但并没有追踪sys.exit(1)
这句异常,实际上sys.exit(1)
这个并不是异常退出原因。try...except...
语句为异常处理语句,一般而言执行完try命令后会在except语句中查询符合的类型,语句会顺序执行,并不是如sys.exit(0)
一样直接退出了。
有另一种捕获sys.exit
调用的方法,代码如下:
1
2
3
4
5
6
7
|
def ():
print
"world"
sys.exitfunc = exitfunc
print
"hello"
sys.exit(
1)
print
"there"
|
输出结果为:
1
2
3
4
|
hello
world
SystemExit:
1
|
这种方式的退出异常类型为代码中显示的1,因为其异常直接导致了进程的推出。
sys.path
sys.path
的功能是获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到。
示例:
1
2
3
|
import sys
sys.path
[
'',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/lib/python2.7/dist-packages/gtk-2.0',
'/usr/lib/python2.7/dist-packages/ubuntu-sso-client']
|
可以采用sys.path.append("自定义模块路径")
增加模块搜索路径(也可以用sys.path.insert
进行列表插入)。以上列出的模块目录,在python执行import module_name
时,会依次从上述列出的路径来搜索对应的模块。如有需要手动添加模块,可放入对应的路径中,如无必要建议不要手动添加路径。``代表当前文件目录。
上问提到的sys.argv
参数传递示例如下:
输入:
1
2
3
4
5
6
7
8
9
10
|
import sys
print
'The command line arguments are:'
for i
in sys.argv:
print i
print
'nnThe PYTHONPATH is', sys.path,
'n'
|
输出:
1
2
3
4
5
6
7
8
9
10
11
|
python using_sys.py we are arguments
The command line arguments are:
using_sys.py
we
are
arguments
The PYTHONPATH
is [
'/home/swaroop/byte/code',
'/usr/lib/python23.zip',
'/usr/lib/python2.3',
'/usr/lib/python2.3/plat-linux2',
'/usr/lib/python2.3/lib-tk',
'/usr/lib/python2.3/lib-dynload',
'/usr/lib/python2.3/site-packages',
'/usr/lib/python2.3/site-packages/gtk-2.0']
|
sys.modules
sys.modules
是一个全局字典,该字典是python启动后就加载在内存中。每当导入新的模块时,sys.modules
将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。
示例:
1
2
3
4
5
|
import sys
print sys.modules.keys()
print sys.modules[
'os']
print sys.modules.values()
|
uiltin_module_names
列表包含了Python解释器中所有内建模块的名称。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
def dump(module):
print module,
"=>",
if module
in sys.builtin_module_names:
print
""
else:
module = _ _import_ _(module)
print module._ _file_ _
dump(
"os")
dump(
"sys")
dump(
"string")
dump(
"strop")
dump(
"zlib")
|
输出(示例,以实际安装情况为准):
1
2
3
4
5
|
os => C:pythonlibos.pyc
sys =>
string => C:pythonlibstring.pyc
strop =>
zlib => C:pythonzlib.pyd
|
sys.platform
语句用于查看当前平台,如win32、linux2等。
1
2
|
>>>
print sys.platform
win32
|
sys.stdin/sys.stdout/sys.stderr
sys.stdin/sys.stdout/sys.stderr变量包含与标准I/O流对应的流对象。如果需要更好地控制输出,而print不能满足你的要求,它们就是你所需要的。你也可以替换它们,这时候你就可以重定向输出和输入到其它设备( device ),或者以非标准的方式处理它们。
我们平时的输入输出方式通过input/raw_input/print实现,即
1
2
|
print
'Hello World!'
print
'Hi, %s!' % raw_input(
'Please enter your name:')
|
上述中,键盘键入的信息则为标准输入,屏幕输出的结果则为标准输出。而上述的例子,与下文采用sys.stdin/sys.stdout的结果是一致的。
1
2
3
4
5
6
7
8
9
10
|
import sys
sys.stdout.write(
'Hello World!')
import sys
print
'Please enter your name:',
name=sys.stdin.readline()[:
-1]
print
'Hi, %s!' % name
|
输入for f in (sys.stdin, sys.stdout, sys.stderr): print f
可查看属性信息。
1
2
3
|
'', mode
'r' at
892210>
'', mode
'w' at
892270>
'', mode
'w at 8922d0>
|
注:通过IPython输出结果与上述有所出入,但上述要表述的信息正确。
stdin/stdout/stderr在Python中都是文件属性的对象,在Python启动时自动与Shell 环境中的标准输入/输出/出错关联。与标准输出print和标准出错所不同的是,stdin/stdout/stderr三者不具备自动回车功能,而标准输入输出则默认自动加了回车。stdin只读,stdout和stderr只写。
使用sys重定向输出
代码如下:
1
2
3
4
5
6
7
|
print
'Dive in'
saveout = sys.stdout
fsock = open(
'out.log',
'w')
sys.stdout = fsock
print
'This message will be logged instead of displayed'
sys.stdout = saveout
fsock.close()
|
(下述sys重定向部分仅做一个拓展)
重定向错误信息
fsock = open(‘error.log’, ‘w’) # 打开你要存储调试信息的日志文件。
sys.stderr = fsock # 将新打开的日志文件的文件对象赋值给stderr以重定向标准错误。
raise Exception, ‘this error will be logged’ # 引发一个异常,没有在屏幕上打印出任何东西,所有正常的跟踪信息已经写进error.log
还要注意你既没有显式关闭日志文件,也没有将 stderr 设回最初的值。
这样挺好,因为一旦程序崩溃 (由于引发的异常),Python 将替我们清理并关闭文件
打印到 stderr
向标准错误写入错误信息是很常见的,所以有一种较快的语法可以立刻导出信息
代码如下:
1
2
3
4
5
|
>>>
print
'entering function'
entering function
>>>
import sys
>>>
print >> sys.stderr,
'entering function'
entering function
|
print 语句的快捷语法可以用于写入任何打开的文件 (或者是类文件对象)。
在这里,你可以将单个print语句重定向到stderr而且不用影响后面的print语句。
更多详见:sys模块官网文档
os模块
Python 的 os 模块封装了常见的文件和目录操作,本文只列出部分常用的方法,更多的方法可以查看官方文档。
常见用法一
- os.mkdir(name) 创建目录
- os.rmdir(name) 删除目录
- os.rename(name) 重命名
- os.remove(file) 删除文件
- os.getcwd() 获取当前工作路径
- os.walk 遍历目录
- os.path.join(path,name) 连接目录与文件名
- os.path.split(name) 分割文件名与目录
- os.path.abspath(name) 获取绝对路径
- os.path.dirname(path) 获取路径
- os.path.basename(path) 获取文件名或文件夹名
- os.path.splitext() 分离文件名与扩展名
- os.path.isfile() 判断给出的路径是否是一个文件
- os.path.isdir() 判断给出的路径是否是一个目录
- os.urandom(n):返回n字节的加密强随机数据
以下面的目录结构为参考,工作目录为 /Users/ethan/coding/python,展示os模块用法
Users/ethan
└── coding
└── python
├── hello.py - 文件
└── web - 目录
os.path.abspath:获取文件或目录的绝对路径
1
2
3
4
5
6
7
8
9
10
|
>>> pwd
/Users/ethan/coding/python
>>> python
>>>
import os
>>> os.path.abspath(
'hello.py')
'/Users/ethan/coding/python/hello.py'
>>> os.path.abspath(
'web')
'/Users/ethan/coding/python/web'
>>> os.path.abspath(
'.')
'/Users/ethan/coding/python'
|
os.path.dirname:获取文件或文件夹的路径
1
2
3
4
5
6
|
>>> os.path.dirname(
'/Users/ethan/coding/python/hello.py')
'/Users/ethan/coding/python'
>>> os.path.dirname(
'/Users/ethan/coding/python/')
'/Users/ethan/coding/python'
>>> os.path.dirname(
'/Users/ethan/coding/python')
'/Users/ethan/coding'
|
os.path.basename:获取文件名或文件夹名
1
2
3
4
5
6
|
>>> os.path.basename(
'/Users/ethan/coding/python/hello.py')
'hello.py'
>>> os.path.basename(
'/Users/ethan/coding/python/')
''
>>> os.path.basename(
'/Users/ethan/coding/python')
'python'
|
os.path.splitext:分离文件名与扩展名
1
2
3
4
5
6
|
>>> os.path.splitext(
'/Users/ethan/coding/python/hello.py')
(
'/Users/ethan/coding/python/hello',
'.py')
>>> os.path.splitext(
'/Users/ethan/coding/python')
(
'/Users/ethan/coding/python',
'')
>>> os.path.splitext(
'/Users/ethan/coding/python/')
(
'/Users/ethan/coding/python/',
'')
|
os.path.split:分离目录与文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
>>> os.path.split(
'/Users/ethan/coding/python/hello.py')
(
'/Users/ethan/coding/python',
'hello.py')
>>> os.path.split(
'/Users/ethan/coding/python/')
(
'/Users/ethan/coding/python',
'')
>>> os.path.split(
'/Users/ethan/coding/python')
(
'/Users/ethan/coding',
'python')
os.path.isfile/os.path.isdir
>>> os.path.isfile(
'/Users/ethan/coding/python/hello.py')
True
>>> os.path.isdir(
'/Users/ethan/coding/python/')
True
>>> os.path.isdir(
'/Users/ethan/coding/python')
True
>>> os.path.isdir(
'/Users/ethan/coding/python/hello.py')
False
|
os.walk
os.walk 是遍历目录常用的模块,它返回一个包含 3 个元素的元祖:(dirpath, dirnames, filenames)。dirpath 是以 string 字符串形式返回该目录下所有的绝对路径;dirnames 是以列表 list 形式返回每一个绝对路径下的文件夹名字;filesnames 是以列表 list 形式返回该路径下所有文件名字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>>
for root, dirs, files
in os.walk(
'/Users/ethan/coding'):
...
print root
...
print dirs
...
print files
...
/Users/ethan/coding
[
'python']
[]
/Users/ethan/coding/python
[
'web2']
[
'hello.py']
/Users/ethan/coding/python/web2
[]
[]
|
常见用法二
其他较常见函数列表如下:
- os.sep:取代操作系统特定的路径分隔符
- os.name:指示你正在使用的工作平台。比如对于Windows,它是’nt’,而对于Linux/Unix用户,它是’posix’。
- os.getenv()和os.putenv:分别用来读取和设置环境变量
- os.listdir(name):返回指定目录下的所有文件和目录名
- os.stat(file):获得文件属性
- os.chmod(file):修改文件权限和时间戳
- os.removedirs(r“c:python”):删除多个目录
- os.environ:对环境变量进行映射
- os.system():运行shell命令
- os.exit():终止当前进程
- os.linesep:给出当前平台的行终止符。例如,Windows使用’rn’,Linux使用’n’而Mac使用’r’
- os.curdir:返回当前目录(’.’)
- os.chdir(dirname):改变工作目录到dirname
- os.pathsep:分隔路径的分隔符
- os.path.existe():检验给出的路径是否真的存在
- os.path.exists(name):判断是否存在文件或目录name
- os.path.getsize(name):或得文件大小,如果name是目录返回0L
- os.path.isabs():判断是否为绝对路径
- os.path.normpath(path):规范path字符串形式
其他
shutil.copyfile("oldfile","newfile")
复制文件,oldfile和newfile都只能是文件
shutil.copy("oldfile","newfile")
oldfile只能是文件夹,newfile可以是文件,也可以是目标目录
shutil.copytree("olddir","newdir")
复制文件夹.olddir和newdir都只能是目录,且newdir必须不存在
shutil.move("oldpos","newpos")
移动文件(目录)
os.rmdir("dir")
只能删除空目录
shutil.rmtree("dir")
空目录、有内容的目录都可以删
典型用法
1
2
3
|
import fileinput
for line
in fileinput.input():
process(line)
|
常用函数
fileinput.input() #返回能够用于for循环遍历的对象
fileinput.filename() #返回当前文件的名称
fileinput.lineno() #返回当前已经读取的行的数量(或者序号)
fileinput.filelineno() #返回当前读取的行的行号
fileinput.isfirstline() #检查当前行是否是文件的第一行
fileinput.isstdin() #判断最后一行是否从stdin中读取
fileinput.close() #关闭队列
常见例子
例子01: 利用fileinput读取一个文件所有行
1
2
3
4
5
6
7
8
|
>>>
import fileinput
>>>
for line
in fileinput.input(
'data.txt'):
print line,
Python
Java
C/C++
Shell
|
命令行方式:
1
2
3
4
5
6
7
8
9
10
11
|
import fileinput
for line
in fileinput.input():
print fileinput.filename(),
'|',
'Line Number:',fileinput.lineno(),
'|: ',line
c:>python test.py data.txt
data.txt | Line Number:
1 |: Python
data.txt | Line Number:
2 |: Java
data.txt | Line Number:
3 |: C/C++
data.txt | Line Number:
4 |: Shell
|
例子02: 利用fileinput对多文件操作,并原地修改内容
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
|
c:Python27>type
1.txt
first
second
c:Python27>type
2.txt
third
fourth
import fileinput
def process(line):
return line.rstrip() +
' line'
for line
in fileinput.input([
'1.txt',
'2.txt'],inplace=
1):
print process(line)
c:Python27>type
1.txt
first line
second line
c:Python27>type
2.txt
third line
fourth line
|
命令行方式:
1
2
3
4
5
6
7
8
9
10
11
|
import fileinput
def process(line):
return line.rstrip() +
' line'
for line
in fileinput.input(inplace =
True):
print process(line)
c:Python27>python test.py
1.txt
2.txt
|
例子03: 利用fileinput实现文件内容替换,并将原文件作备份
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
|
Python
Java
C/C++
Shell
import fileinput
for line
in fileinput.input(
'data.txt',backup=
'.bak',inplace=
1):
print line.rstrip().replace(
'Python',
'Perl')
Python
Java
C/C++
Shell
import fileinput
for line
in fileinput.input():
print
'Tag:',line,
d:>python Learn.py < data.txt > data_out.txt
|
例子04: 利用fileinput将CRLF文件转为LF
1
2
3
4
5
6
7
8
|
import fileinput
import sys
for line
in fileinput.input(inplace=
True):
if line[
-2:] ==
"rn":
line = line +
"n"
sys.stdout.write(line)
|
例子05: 利用fileinput对文件简单处理
略
例子06: 利用fileinput批处理文件
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
|
import fileinput
import glob
for line
in fileinput.input(glob.glob(
"test*.txt")):
if fileinput.isfirstline():
print
'-'*
20,
'Reading %s...' % fileinput.filename(),
'-'*
20
print str(fileinput.lineno()) +
': ' + line.upper(),
>>>
-------------------- Reading test.txt... --------------------
1: AAAAA
2: BBBBB
3: CCCCC
4: DDDDD
5: FFFFF
-------------------- Reading test1.txt... --------------------
6: FIRST LINE
7: SECOND LINE
-------------------- Reading test2.txt... --------------------
8: THIRD LINE
9: FOURTH LINE
-------------------- Reading test3.txt... --------------------
10: THIS IS LINE
1
11: THIS IS LINE
2
12: THIS IS LINE
3
13: THIS IS LINE
4
|
例子07: 利用fileinput及re做日志分析: 提取所有含日期的行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#--样本文件--
aaa
1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough...
bbb
1970-01-02 10:20:30 Error: **** Due to System Out of Memory...
ccc
#---测试脚本---
import re
import fileinput
import sys
pattern = 'd{4}-d{2}-d{2} d{2}:d{2}:d{2}'
for line in fileinput.input('error.log',backup='.bak',inplace=1):
if re.search(pattern,line):
sys.stdout.write("=> ")
sys.stdout.write(line)
#---测试结果---
=> 1970-01-01 13:45:30 Error: **** Due to System Disk spacke not enough...
=> 1970-01-02 10:20:30 Error: **** Due to System Out of Memory...
|
例子08: 利用fileinput及re做分析: 提取符合条件的电话号码
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
|
010
-110
-12345
800
-333
-1234
010
-99999999
05718888888
021
-88888888
import re
import fileinput
pattern =
'[010|021]-d{8}'
for line
in fileinput.input(
'phone.txt'):
if re.search(pattern,line):
print
'=' *
50
print
'Filename:'+ fileinput.filename()+
' | Line Number:'+str(fileinput.lineno())+
' | '+line,
>>>
==================================================
Filename:phone.txt | Line Number:
3 |
010
-99999999
==================================================
Filename:phone.txt | Line Number:
5 |
021
-88888888
>>>
|
例子09: 利用fileinput实现类似于grep的功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import sys
import re
import fileinput
pattern= re.compile(sys.argv[
1])
for line
in fileinput.input(sys.argv[
2]):
if pattern.match(line):
print fileinput.filename(), fileinput.filelineno(), line
$ ./test.py
import.*re *.py
addressBook.py
2
import re
addressBook1.py
10
import re
addressBook2.py
18
import re
test.py
238
import re
|
例子10: 利用fileinput做正则替换
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#---测试样本: input.txt
* [Learning Python](#author:Mark Lutz)
#---测试脚本: test.py
import fileinput
import re
for line in fileinput.input():
line = re.sub(r'*
(.∗)
#(.*)', r' 1', line.rstrip())
print(line)
#---输出结果:
c:Python27>python test.py input.txt
Learning Python
例子11: 利用fileinput做正则替换,不同字模块之间的替换
#---测试样本:test.txt
[@!$First]&[*%-Second]&[Third]
#---测试脚本:test.py
import re
import fileinput
regex = re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')
#整行以&分割,要实现[@!$First]与[*%-Second]互换
for line in fileinput.input('test.txt',inplace=1,backup='.bak'):
print regex.sub(r'32145',line),
#---输出结果:
[*%-Second]&[@!$First]&[Third]
例子12: 利用fileinput根据argv命令行输入做替换
#---样本数据: host.txt
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
127.0.0.1 localhost
192.168.100.2 www.test2.com
192.168.100.3 www.test3.com
192.168.100.4 www.test4.com
#---测试脚本: test.py
import sys
import fileinput
source = sys.argv[1]
target = sys.argv[2]
files = sys.argv[3:]
for line in fileinput.input(files,backup='.bak',openhook=fileinput.hook_encoded("gb2312")):
#对打开的文件执行中文字符集编码
line = line.rstrip().replace(source,target)
print line
#---输出结果:
c:>python test.py 192.168.100 127.0.0 host.txt
#将host文件中,所有192.168.100转换为:127.0.0
127.0.0.1 localhost
127.0.0.2 www.test2.com
127.0.0.3 www.test3.com
127.0.0.4 www.test4.com
|
集合(set)类型
python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和sysmmetric difference(对称差集)等数学运算。注:set不需要通过import引入。
sets 支持 x in set, len(set),和 for x in set。作为一个无序的集合,sets不记录元素位置或者插入点。因此,sets不支持 indexing, slicing, 或其它类序列(sequence-like)的操作。
set示例
1
2
3
4
5
6
7
|
>>> a = set([
1,
2,
3])
>>> b = set([
2,
3,
4])
>>>
print a,b
set([
1,
2,
3]), set([
2,
3,
4])
>>> x = set(
'spam')
>>>
print x
set([
'a',
'p',
's',
'm'])
|
集合set与列表和元组不同,集合是无序的,也无法通过数字进行索引。同时,集合中的元素不能重复。利用集合set元素不重复这个特性,可以去除list列表中的重复值。
1
2
3
4
5
6
7
8
|
>>> a = [
11,
22,
33,
44,
11,
22]
>>> b = set(a)
>>> b
set([
33,
11,
44,
22])
>>> c = [i
for i
in b]
>>> c
[
33,
11,
44,
22]
|
基本操作
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
a = t | s
b = t & s
c = t – s
d = t ^ s
t.add(
'x')
s.update([
10,
37,
42])
t.remove(
'H')
len(s)
x
in s
x
not
in s
s.issubset(t)
s <= t
s.issuperset(t)
s >= t
s.union(t)
s | t
s.intersection(t)
s & t
s.difference(t)
s - t
s.symmetric_difference(t)
s ^ t
s.copy()
s.update(t)
s |= t
s.intersection_update(t)
s &= t
s.difference_update(t)
s -= t
s.symmetric_difference_update(t)
s ^= t
s.add(x)
s.remove(x)
s.discard(x)
s.pop()
s.clear()
|
参考: Python集合(set)类型的操作
range和xrange
range和xrange都不用引入import,都可直接使用。
range函数用法:range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。
range示例:
1
2
3
4
5
6
|
>>> range(
5)
[
0,
1,
2,
3,
4]
>>> range(
1,
5)
[
1,
2,
3,
4]
>>> range(
0,
6,
2)
[
0,
2,
4]
|
xrange用法和range完全相同,所不同的是生成的不是一个数组,而是一个生成器。
1
2
3
4
5
6
7
|
>>> y = xrange(
5)
>>>
print y
xrange(y)
>>>
print type(y)
'xrange'>
>>> list(y)
[
0,
1,
2,
3,
4]
|
由上面的示例可以知道:要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间.
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
|
for i
in range(
0,
100):
print i
for i
in xrange(
0,
100):
print i
a = range(
0,
100)
print type(a)
print a
print a[
0], a[
1]
'list'>
[
0,
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,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99]
0
1
a = xrange(
0,
100)
print type(a)
print a
print a[
0], a[
1]
'xrange'>
xrange(
100)
0
1
|
time
在Python中,与时间处理有关的模块就包括:time,datetime以及calendar
在开始之前,首先要说明这几点:
- 在Python中,通常有这几种方式来表示时间:1)时间戳timestamp; 2)格式化的时间字符串; 3)元组(struct_time,共九个元素)。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。
- UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。
- 时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。
- 元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有全球统一时间gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:
元组的九个元素如下表所示:
索引(Index) |
属性(Attribute) |
值(Values) |
0 |
tm_year(年) |
比如2011 |
1 |
tm_mon(月) |
1 - 12 |
2 |
tm_mday(日) |
1 - 31 |
3 |
tm_hour(时) |
0 - 23 |
4 |
tm_min(分) |
0 - 59 |
5 |
tm_sec(秒) |
0 - 61(包含闰秒和双闰秒) |
6 |
tm_wday(weekday) |
0 - 6(0表示周一) |
7 |
tm_yday(一年中的第几天) |
1 - 366 |
8 |
tm_isdst(是否是夏令时) |
默认为-1,0,1 |
常用函数
time.localtime([secs])
将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。
1
2
3
4
|
>>> time.localtime()
time.struct_time(tm_year=
2011, tm_mon=
5, tm_mday=
5, tm_hour=
14, tm_min=
14, tm_sec=
50, tm_wday=
3, tm_yday=
125, tm_isdst=
0)
>>> time.localtime(
1304575584.1361799)
time.struct_time(tm_year=
2011, tm_mon=
5, tm_mday=
5, tm_hour=
14, tm_min=
6, tm_sec=
24, tm_wday=
3, tm_yday=
125, tm_isdst=
0)
|
time.gmtime([secs])
和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
1
2
|
>>>time.gmtime()
time.struct_time(tm_year=
2011, tm_mon=
5, tm_mday=
5, tm_hour=
6, tm_min=
19, tm_sec=
48, tm_wday=
3, tm_yday=
125, tm_isdst=
0)
|
time.sleep(secs)
休眠(不做任何事情,推迟)secs秒
time.time()
返回当前时间的时间戳。
1
2
|
>>> time.time()
1304575584.1361799
|
time.mktime(t)
将一个struct_time转化为时间戳。
1
2
|
>>> time.mktime(time.localtime())
1304576839.0
|
time.sleep(secs)
线程推迟指定的时间运行。单位为秒。
time.clock()
这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间。(实际上是以WIN32上QueryPerformanceCounter()为基础,它比毫秒表示更为精确)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import time
if __name__ ==
'__main__':
time.sleep(
1)
print
"clock1:%s" % time.clock()
time.sleep(
1)
print
"clock2:%s" % time.clock()
time.sleep(
1)
print
"clock3:%s" % time.clock()
clock1:
3.35238137808e-006
clock2:
1.00004944763
clock3:
2.00012040636
|
time.asctime([t])
把一个表示时间的元组或者struct_time表示为这种形式:’Sun Jun 20 23:21:05 1993’。如果没有参数,将会将time.localtime()作为参数传入。
1
2
|
>>> time.asctime()
'Thu May 5 14:55:43 2011'
|
time.ctime([secs])
把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
1
2
3
4
5
6
|
>>> time.ctime()
'Thu May 5 14:58:09 2011'
>>> time.ctime(time.time())
'Thu May 5 14:58:39 2011'
>>> time.ctime(
1304579615)
'Thu May 5 15:13:35 2011'
|
把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。
日期格式化对照表如下:
|格式 |含义|
|-|-|
|%a |本地(locale)简化星期名称|
|%A |本地完整星期名称|
|%b |本地简化月份名称|
|%B |本地完整月份名称|
|%c |本地相应的日期和时间表示|
|%d |一个月中的第几天(01 - 31)|
|%H |一天中的第几个小时(24小时制,00 - 23)|
|%I |第几个小时(12小时制,01 - 12)|
|%j |一年中的第几天(001 - 366)|
|%m |月份(01 - 12)|
|%M |分钟数(00 - 59)|
|%p |本地am或者pm的相应符|
|%S |秒(01 - 61)|
|%U |一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周|
|%w |一个星期中的第几天(0 - 6,0是星期天)|
|%W |和%U基本相同,不同的是%W以星期一为一个星期的开始|
|%x |本地相应日期|
|%X |本地相应时间|
|%y |去掉世纪的年份(00 - 99)|
|%Y |完整的年份|
|%Z |时区的名字(如果不存在为空字符)|
|%% |‘%’字符|
按常用习惯排列如下:
|格式 |含义|
|-|-|
|%Y |完整的年份 例:2017|
|%m |月份(01 - 12)例:09|
|%d |一个月中的第几天(01 - 31) 例:21|
|%H |一天中的第几个小时(24小时制,00 - 23)|
|%M |分钟数(00 - 59)|
|%S |秒(01 - 61)|
|%B |本地完整月份名称 例:September|
|%A |本地完整星期名称 例:Monday|
|%y |去掉世纪的年份(00 - 99) 即短日期表示 例:17(年)|
|%b |本地简化月份名称 例:Sep|
|%a |本地(locale)简化星期名称 例:Mon|
|%c |本地相应的日期和时间表示 例:09/21/17 17:59:07|
|%x |本地相应日期 例:09/21/17|
|%X |本地相应时间 例:17:59:07|
|%I |第几个小时(12小时制,01 - 12)|
|%p |本地am或者pm的相应符|
|%j |一年中的第几天(001 - 366)|
|%U |一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周|
|%W |和%U基本相同,不同的是%W以星期一为一个星期的开始|
|%w |一个星期中的第几天(0 - 6,0是星期天)|
|%Z |时区的名字(如果不存在为空字符)|
|%% |‘%’字符|
备注:
- “%p”只有与“%I”配合使用才有效果。
- 文档中强调确实是0 - 61,而不是59,闰年秒占两秒(汗一个)。
- 当使用strptime()函数时,只有当在这年中的周数和天数被确定的时候%U和%W才会被计算。
举个例子:
1
2
|
>>> time.strftime(
"%Y-%m-%d %X", time.localtime())
'2011-05-05 16:37:06'
|
把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
1
2
|
>>> time.strptime(
'2011-05-05 16:37:06',
'%Y-%m-%d %X')
time.struct_time(tm_year=
2011, tm_mon=
5, tm_mday=
5, tm_hour=
16, tm_min=
37, tm_sec=
6, tm_wday=
3, tm_yday=
125, tm_isdst=
-1)
|
在这个函数中,format默认为:”%a %b %d %H:%M:%S %Y”。
最后,我们来对time模块进行一个总结。根据之前描述,在Python中共有三种表达方式:1)timestamp 2)tuple或者struct_time 3)格式化字符串。
它们之间的转化如图所示:
Calendar
此模块的函数都是日历相关的,例如打印某月的字符月历。
星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用calendar.setfirstweekday()函数。
常用函数
序号 |
函数及描述 |
1 |
calendar.calendar(year,w=2,l=1,c=6) |
|
返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21 W+18+2 C。l是每星期行数。参数可省略 |
2 |
calendar.firstweekday() |
|
返回当前每周起始日期的设置。默认情况下,首次载入caendar模块时返回0,即星期一。 |
3 |
calendar.isleap(year) |
|
是闰年返回True,否则为false。 |
4 |
calendar.leapdays(y1,y2) |
|
返回在Y1,Y2两年之间的闰年总数。 |
5 |
calendar.month(year,month,w=2,l=1) |
|
返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。参数可省略 |
6 |
calendar.monthcalendar(year,month) |
|
返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。list形式 |
7 |
calendar.monthrange(year,month) |
|
返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。例:(2017, 10) -> (6, 31),第二个参数为当月日期数,第一个参数待深究 |
8 |
calendar.prcal(year,w=2,l=1,c=6) |
|
直接打印出整理好的年历。相当于 print calendar.calendar(year,w,l,c). |
9 |
calendar.prmonth(year,month,w=2,l=1) |
|
直接打印出月日历。相当于 print calendar.month(year,w,l,c)。 |
10 |
calendar.setfirstweekday(weekday) |
|
设置每周的起始日期码。0(星期一)到6(星期日)。 |
11 |
calendar.timegm(tupletime) |
|
和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间辍(1970纪元后经过的浮点秒数)。 |
12 |
calendar.weekday(year,month,day) |
|
返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。 |
建议实际使用 a=calendar.function()
, print a
方式输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import calendar
cal = calendar.month(
2016,
1)
print
"以下输出2016年1月份的日历:"
print cal
January
2016
Mo Tu We Th Fr Sa Su
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
31
|
datetime
datatime模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。
date类
date 类表示一个日期(由年、月、日组成),其原型如下:
class datetime.date(year, month, day)
参数说明:
- year 的范围是 [MINYEAR, MAXYEAR],即 [1, 9999];
- month 的范围是[1, 12]。(月份是从1开始的,不是从0开始);
- day 的最大值根据给定的year, month参数来决定。例如闰年2月份有29天;
date 类定义了一些常用的类方法与类属性:
- date.max、date.min:date对象所能表示的最大、最小日期;
- date.resolution:date对象表示日期的最小单位。这里是天。
- date.today():返回一个表示当前本地日期的 date 对象;
- date.fromtimestamp(timestamp):根据给定的时间戮,返回一个 date 对象;
- datetime.fromordinal(ordinal):将Gregorian日历时间转换为date对象;(Gregorian Calendar:一种日历表示方法,类似于我国的农历,西方国家使用比较多)
使用示例:
1
2
3
4
5
6
7
8
9
10
|
>>> datetime.date.max
datetime.date(
9999,
12,
31)
>>> datetime.date.min
datetime.date(
1,
1,
1)
>>> datetime.date.resolution
datetime.timedelta(
1)
>>> datetime.date.today()
datetime.date(
2016,
5,
12)
>>> datetime.date.fromtimestamp(time.time())
datetime.date(
2016,
5,
12)
|
date提供的实例方法和属性:
- date.year、date.month、date.day:年、月、日;
- date.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
- date.timetuple():返回日期对应的time.struct_time对象;
- date.toordinal():返回日期对应的Gregorian Calendar日期; 大专栏 Python学习笔记3:Python常见模块的用法
- date.weekday():返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
- data.isoweekday():返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
- date.isocalendar():返回格式如(year,month,day)的元组;
- date.isoformat():返回格式如’YYYY-MM-DD’的字符串;
- date.strftime(fmt):自定义格式化字符串。
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
>>> today = datetime.date.today()
>>> today.year
2016
>>> today.month
5
>>> today.day
12
>>> tomorrow = today.replace(day=
13)
>>> tomorrow
datetime.date(
2016,
5,
13)
>>> tomorrow.timetuple()
time.struct_time(tm_year=
2016, tm_mon=
5, tm_mday=
13, tm_hour=
0, tm_min=
0, tm_sec=
0, tm_wday=
4, tm_yday=
134, tm_isdst=
-1)
>>> tomorrow.toordinal()
736097
>>> tomorrow.weekday()
4
>>> tomorrow.isoweekday()
5
>>> tomorrow.isocalendar()
(
2016,
19,
5)
>>> tomorrow.isoformat()
'2016-05-13'
>>> tomorrow.strftime(
"%y-%m-%d")
'16-05-13'
|
date 重载了简单的运算符
1
2
3
4
5
6
7
8
9
|
date2 = date1 + timedelta
date2 = date1 - timedelta
timedelta = date1 - date2
date1 < date2
|
使用示例:
1
2
3
4
5
6
7
8
9
10
11
|
>>> now = datetime.date.today()
>>> now
datetime.date(
2016,
5,
12)
>>> now += datetime.date.resolution
>>> now
datetime.date(
2016,
5,
13)
>>> now -= datetime.date.resolution
>>> now
datetime.date(
2016,
5,
12)
>>> now < datetime.date.max
True
|
Time类
time 类表示时间(由时、分、秒以及微秒组成),其原型如下:
class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
参数说明:
- hour 的范围为[0, 24),
- minute 的范围为[0, 60),
- second 的范围为[0, 60),
- microsecond 的范围为[0, 1000000),
- tzinfo 表示时区信息。
time 类定义的类属性:
- time.min、time.max:time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
- time.resolution:时间的最小单位,这里是1微秒;
使用示例:
1
2
3
4
5
6
|
>>> datetime.time.min
datetime.time(
0,
0)
>>> datetime.time.max
datetime.time(
23,
59,
59,
999999)
>>> datetime.time.resolution
datetime.timedelta(
0,
0,
1)
|
time类提供的实例方法和属性:
- time.hour、time.minute、time.second、time.microsecond:时、分、秒、微秒;
- time.tzinfo:时区信息;
- time.replace([hour[, minute[, second[, microsecond[, tzinfo]]]]]):创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变);
- time.isoformat():返回型如”HH:MM:SS”格式的字符串表示;
- time.strftime(fmt):返回自定义格式化字符串。
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>> tm = datetime.time(
18,
18,
18)
>>> tm.hour
18
>>> tm.minute
18
>>> tm.second
18
>>> tm.microsecond
0
>>> tm.tzinfo
>>> tm.isoformat()
'18:18:18'
>>> tm.replace(hour=
20)
datetime.time(
20,
18,
18)
>>> tm.strftime(
"%I:%M:%S %p")
'06:18:18 PM'
|
time 类的对象只能进行比较,无法进行加减操作。
datetime 类
datetime 是 date 与 time 的结合体,包括 date 与 time 的所有信息。其原型如下:
class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
各参数的含义与date、time的构造函数中的一样,要注意参数值的范围。
datetime类定义的类属性与方法:
- datetime.min、datetime.max:datetime所能表示的最小值与最大值;
- datetime.resolution:datetime最小单位;
- datetime.today():返回一个表示当前本地时间的datetime对象;
- datetime.now([tz]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间;
- datetime.utcnow():返回一个当前utc时间的datetime对象;
- datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
- datetime.utcfromtimestamp(timestamp):根据时间戮创建一个datetime对象;
- datetime.combine(date, time):根据date和time,创建一个datetime对象;
- datetime.strptime(date_string, format):将格式字符串转换为datetime对象,data 与 time 类没有提供该方法。
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
>>> datetime.datetime.min
datetime.datetime(
1,
1,
1,
0,
0)
>>> datetime.datetime.max
datetime.datetime(
9999,
12,
31,
23,
59,
59,
999999)
>>> datetime.datetime.resolution
datetime.timedelta(
0,
0,
1)
>>>
print datetime.datetime.resolution
0:
00:
00.000001
>>> today = datetime.datetime.today()
>>> today
datetime.datetime(
2016,
5,
12,
12,
46,
47,
246240)
>>> datetime.datetime.now()
datetime.datetime(
2016,
5,
12,
12,
47,
9,
850643)
>>> datetime.datetime.utcnow()
datetime.datetime(
2016,
5,
12,
4,
47,
42,
188124)
>>> datetime.datetime.fromtimestamp(time.time())
datetime.datetime(
2016,
5,
12,
12,
48,
40,
459676)
>>> datetime.datetime.combine(datetime.date(
1990,
10,
05), datetime.time(
18,
18,
18))
datetime.datetime(
1990,
10,
5,
18,
18,
18)
>>> datetime.datetime.strptime(
"2010-04-07 01:48:16.234000",
"%Y-%m-%d %H:%M:%S .%f")
datetime.datetime(
2010,
4,
7,
1,
48,
16,
234000)
|
datetime 的实例方法与属性
datetime类提供的实例方法与属性大部分功能与 date 和 time 类似,这里仅罗列方法名不再赘述:
- datetime.year、month、day、hour、minute、second、microsecond、tzinfo:
- datetime.date():获取date对象;
- datetime.time():获取time对象;
- datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]):
- datetime.timetuple()
- datetime.utctimetuple()
- datetime.toordinal()
- datetime.weekday()
- datetime.isocalendar()
- datetime.isoformat([sep])
- datetime.ctime():返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
- datetime.strftime(format)
datetime 对象同样可以进行比较,或者相减返回一个时间间隔对象,或者日期时间加上一个间隔返回一个新的日期时间对象。
timedelta 类
datetime.timedelta 对象代表两个时间之间的的时间差,两个 date 或 datetime 对象相减时可以返回一个timedelta 对象。其原型如下:
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
所有参数可选,且默认都是0,参数的值可以是整数,浮点数,正数或负数。
内部只存储days,seconds,microseconds,其他参数的值会自动按如下规则抓转换:
- 1 millisecond(毫秒) 转换成 1000 microseconds(微秒)
- 1 minute 转换成 60 seconds
- 1 hour 转换成 3600 seconds
- 1 week转换成 7 days
b = a + datetime.timedelta(hours=5)
c = a + datetime.timedelta(weeks=1)
三个参数的取值范围分别为:
- 0 <= microseconds < 1000000
- 0 <= seconds < 3600*24 (the number of seconds in one day)
- -999999999 <= days <= 999999999
timedelta 类定义的类属性:
- timedelta.min:时间间隔对象的最小值,即 timedelta(-999999999).
- timedelta.max:时间间隔对象的最大值,即 timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999).
- timedelta.resolution:时间间隔的最小单位,即 timedelta(microseconds=1).
使用示例:
1
2
3
4
5
6
7
8
|
>>> datetime.timedelta.min
datetime.timedelta(
-999999999)
>>> datetime.timedelta.max
datetime.timedelta(
999999999,
86399,
999999)
>>> datetime.timedelta.resolution
datetime.timedelta(
0,
0,
1)
>>>
print datetime.timedelta.resolution
0:
00:
00.000001
|
timedelta 实例方法
- timedelta.total_seconds():计算时间间隔的总秒数
使用示例:
1
2
|
>>> datetime.timedelta.resolution.total_seconds()
1e-06
|
timeit
timeit模块提供了一种简便的方法来为Python中的小块代码进行计时。它有三种使用方式,从命令行调用,从Python交互解释器调用,或者直接在脚本代码中进行调用。基于实际应用出发,本文阐述timeit模块在交互解释器以及脚本中的基础使用方法。
主要方法
timeit模块主要方法有三个,timeit()、Timer()和repeat()用法。
1
2
3
4
5
6
|
timeit(stmt=
"pass", setup=
"pass", timer=default_timer, number=default_number)
= Timer(stmt, setup, timer).timeit(number)
repeat(stmt=
"pass", setup=
"pass", timer=default_timer, repeat=default_repeat, number=default_number)
= Timer(stmt, setup, timer).repeat(repeat, number)
|
其中:
- stmt是执行语句,setup是导入执行语句环境。repeat 是重复整个测试的次数,number 是每个测试中执行语句的次数。
2.default_timer 在 win32 下是 time.clock(),在 linux 下是 time.time()
- default_repeat = 3,default_number = 1000000
上述用法示例可如下:
1
2
3
4
5
6
7
8
|
>>>
import timeit
>>> t = timeit.Timer(
"soundex.soundex('Pilgrim')",
"import soundex")
>>> t.timeit()
8.21683733547
>>> t.repeat(
3,
2000000)
[
16.48319309109,
16.46128984923,
16.44203948912]
>>> min(t.repeat(
3,
1000000))
8.22203948912
|
或如下使用:
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
|
import random
import timeit
def randDiff( k,n ):
p = []
y1 = [random.randrange(
1,n+
1)
for i
in range(n)]
y2 = []
y2.extend(y1)
y1.sort()
for j
in range(k):
temp1 = y1[j]
temp2 = y2.index(temp1)
p.append(temp2 +
1)
y2[temp2] =
-1
return p
def randDif(k,n):
'新函数,生成k个1到n之间不相等的随机数'
if k>n:
return []
a = range(
1,n+
1)
random.shuffle(a)
return a[:k]
if __name__==
'__main__':
print timeit.repeat(
"randDiff(3, 10)",
"from __main__ import randDiff", timeit.default_timer,
3,
10000)
print timeit.repeat(
"randDif(3, 10)",
"from __main__ import randDif", timeit.default_timer,
3,
10000)
|
在Python交互解释器中的使用
timeit函数基本用法
1
2
|
import timeit
timeit.timeit(stmt=
'pass', setup=
'pass', timer=, number=
1000000)
|
使用示例:
1
2
3
|
>>>
import timeit
>>>timeit.timeit(
'"-".join(str(n) for n in range(100))', number=
10000)
0.21051692962646484
|
repeat函数
repeat函数,指定整个试验的重复次数,返回一个包含了每次试验的执行时间的列表。
1
2
|
>>> timeit.repeat(
'"-".join(str(n) for n in range(100))',repeat=
3, number=
10000)
[
0.21938705444335938,
0.21767210960388184,
0.21688294410705566]
|
在脚本程序中的使用
timeit模块同样可以在脚本中直接使用。使用方法还是调用上述的函数。但是在脚本中时需要为setup传入一条字符串形式的语句,用于构建执行环境。也可参照基本用法处的代码示例。
1
2
3
4
5
6
7
8
9
|
import timeit
def test():
L = []
for i
in range(
100):
L.append(i)
if __name__ ==
'__main__':
print timeit.timeit(
"test()", setup=
"from __main__ import test")
|
random
random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串。
random的用法主要包括random()、uniform()、randrang()、choice()、shuffle()、sample()几种用法。
random.random()
用于生成一个随机浮点数:range[0.0,1.0)
1
2
|
import random
random.random()
|
用于生成一个指定范围内的随机浮点数,a,b为上下限,只要a!=b,就会生成介于两者之间的一个浮点数,若a=b,则生成的浮点数就是a
1
2
3
4
|
import random
random.uniform(
10,
20)
random.uniform(
20,
10)
random.uniform(
10,
10)
|
random.randint(a,b)
用于生成一个指定范围内的整数,a为下限,b为上限,生成的随机整数a<=n<=b;若a=b,则n=a;若a>b,报错
1
2
3
4
|
import random
random.randint(
10,
20)
random.randint(
10,
10)
random.randint(
20,
10)
|
random.randrange([start], stop [,step])
从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省值为1
1
2
3
4
|
import random
random.randrange(
10,
100)
random.randrange(
10,
100,
4)
random.choice(range(
10,
100,
4))
|
random.choice(sequence)
从序列中获取一个随机元素,参数sequence表示一个有序类型,并不是一种特定类型,泛指list,tuple,字符串等
1
2
3
4
5
6
7
8
9
|
import random
random.choice(range(
10))
random.choice(range(
10,
100,
2))
random.choice(
"I love python")
random.choice((
"I love python"))
random.choice([
"I love python"])
random.choice(
"I",
"love",
"python")
random.choice((
"I",
"love",
"python"))
random.choice([
"I",
"love",
"python"])
|
random.shuffle(x[,random])
用于将一个列表中的元素打乱
1
2
3
4
|
import random
list=[
'I',
'love',
'python',
'very',
'much']
random.shuffle(list)
print list
|
random.sample(sequence,k)
从指定序列中随机获取k个元素作为一个片段返回,sample函数不会修改原有序列
1
2
3
4
5
6
7
8
9
10
|
import random
a=
'123456789'
b=[
1,
2,
3,
4,
5,
6,
7,
8,
9]
c=[
'a',
'b',
'c',
'd',
'e']
random.sample(a,
3)
random.sample(b,
3)
random.sample(c,
3)
print a
print b
print c
|
shelve
Shelve是python中一个用于持久化存储的模块,采用字典的存储形式。Shelve模块的好处是,基本上任何python对象都可以作为存储的键。作为一种简单的数据存储方案,其最有用的函数为open()
。
open()
函数接收的参数就是文件名,然后返回一个shelf对象,可以用它来存储东西,也可以简单地把他当作一个字典。当存储完毕的时候,调用close()函数来关闭 。
需要注意的是,为了正确地使用shelve模块修改存储的对象,必须将临时变量绑定到获得的副本上,并且在修改后重新存储这个副本。或者直接将open()中writeback参数设为True。否则会导致修改后的内容没有存储好,导致数据丢失。
1
2
3
4
5
6
|
>>>
import shelve
>>> s = shelve.open(
'test.dat')
>>> s[
'x'] = [
'a',
'b',
'c']
>>> s[
'x'].append(
'd')
>>> s[
'x']
[
'a',
'b',
'c']
|
解决办法之一为将临时变量绑定到获得的副本上。
1
2
3
4
5
|
>>> temp = s[
'x']
>>> temp.append(
'd')
>>> s[
'x'] = temp
>>> s[
'x']
[
'a',
'b',
'c',
'd']
|
一个完整的示例如下:
创建shelf对象,使用函数shelve.open()(使用的是anydbm)来存储数据。使用类或简单的调用。
1
2
3
4
5
6
7
|
import shelve
s = shelve.open(
'test_shelf.db')
try:
s[
'key1'] = {
'int':
10,
'float':
9.5,
'string':
'Sample Data'}
finally:
s.close()
|
注意要使用try...finally...
来调用。
访问已存储的数据,打开shelf,可以像字典一样进行使用。
1
2
3
4
5
6
7
8
9
10
11
12
|
s = shelve.open(
'test_shelf.db')
try:
existing = s[
'key1']
finally:
s.close()
print(existing)
>>> python shelve_create.py
>>> python shelve_existing.py
{
'int':
10,
'float':
9.5,
'string':
'Sample data'}
|
dbm模块不支持多个应用同时写入同一数据库,如果客户端或程序不会修改shelf,请指定shelve以只读方式打开数据库。
1
2
3
4
5
6
7
|
s = shelve.open(
'test_shelf.db', flag=
'r')
try:
existing = s[
'key1']
finally:
s.close()
print existing
|
当数据库以只读模式打开,但又试图更改数据库时,会引起一个访问出错异常。这一异常类型依赖于在创建数据库时被anydbm选择的数据库模块。
写回示例。默认情况下,Shelves不去追踪可变对象的修改。意思就是,如果你改变了已存储在shelf中的一个项目的内容,就必须重新存储该项目来更新shelf.
1
2
3
4
5
6
7
8
9
10
11
12
|
s = shelve.open(
'test_shelf.db')
try:
print s[
'key1']
s[
'key'][
'new_value'] =
'this is not here before'
finally:
s.close()
s = shelve.open(
'test_shelf.db', writeback =
True)
try:
print s[
'key1']
finally:
s.close()
|
在这个例子中,没有对字典的关键字key1的内容进行存储,虽然打开时设置了writeback,因此重新打开shelf时,key1内容没有改变。
1
2
3
4
|
>>> python shelve_create.py
>>> python shelve_withoutwriteback.py
{
'int':
10,
'float':
9.5,
'string':
'Sample data'}
{
'int':
10,
'float':
9.5,
'string':
'Sample data'}
|
为了自动捕捉存储在shelf中的可变对象所发生的改变,需改变前设置writeback可用.writeback标志导致shelf使用一缓存来记住从数据库中调出的所有对象。当shelf关闭的时候,每一个缓存中的对象也重新写回数据库。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
s = shelve.open(
'test_shelf.db', writeback=
True)
try:
print(s[
'key1'])
s[
'key1'][
'new_value'] =
'this was not here before'
print(s[
'key1'])
finally;
s.close()
s = shelve.open(
'test_shelf.db', writeback=
True)
try:
print(s[
'key1'])
finally:
s.close()
>>> python shelve_create.py
>>> python shelve_writeback.py
{
'int':
10,
'float':
9.5,
'string':
'Sample data'}
{
'int':
10,
'new_value':
'this was not here before',
'float':
9.5,
'string':
'Sample data'}
{
'int':
10,
'new_value':
'this was not here before',
'float':
9.5,
'string':
'Sample data'}
|
虽然使用writeback模式可用减少出错几率,也能更加透明化对象的持久性。但是,不是每种情况都要使用writeback模式。原因看到前面的示例,应该能猜到。当shelf打开时,缓存就要占用额外的内存。 并且,当shelf关闭时,同样会对缓存中的对象再次写回数据库,增加了开销。即使没有进行改变,仍然会进行数据写回。比较好的方式是,确认需要写入数据时,再设置writeback,读数据时设置只读或默认即可。
csv
csv库可识别Microsoft Excel所使用的CSV编码规则。csv库还包含修改分隔字符等,出于实际csv文件应用考虑,这里不阐述,如有需要可之后自行查阅。
CSV格式简介
逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。
CSV文件注意点
如果你正在读取CSV数据并将它们转换为命名元组,需要注意对列名进行合法性认证。一个CSV格式文件有一个包含非法标识符的列头行,这样最终会导致在创建一个命名元组时产生一个ValueError异常而失败。为了解决这问题,你可能不得不先去修正列标题。
1
2
3
4
5
6
7
8
9
|
import re
with open(
'stock.csv')
as f:
f_csv = csv.reader(f)
headers = [ re.sub(
'[^a-zA-Z_]',
'_', h)
for h
in next(f_csv) ]
Row = namedtuple(
'Row', headers)
for r
in f_csv:
row = Row(*r)
...
|
还有重要的一点需要强调的是,CSV产生的数据都是字符串类型的,它不会做任何其他类型的转换。如果你需要做这样的类型转换,你必须自己手动去实现。
简单使用
1
2
3
4
5
6
7
8
9
10
11
12
|
import csv
with open(
'some.csv',
'rb')
as f:
reader = csv.reader(f)
for row
in reader:
import csv
with open(
'some.csv',
'wb')
as f:
writer = csv.writer(f)
writer.writerows(someiterable)
|
字典方式读写
csv还提供了一种类似于字典方式的读写,方式如下:
1
2
3
|
class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)
class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)
|
其中fieldnames指定字典的key值,如果reader里没有指定那么默认第一行的元素(header),在writer里一定要指定这个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
>>>
import csv
>>>
with open(
'names.csv')
as csvfile:
... reader = csv.DictReader(csvfile)
...
for row
in reader:
... print(row[
'first_name'], row[
'last_name'])
...
Baked Beans
Lovely Spam
Wonderful Spam
import csv
with open(
'names.csv',
'w')
as csvfile:
fieldnames = [
'first_name',
'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({
'first_name':
'Baked',
'last_name':
'Beans'})
writer.writerow({
'first_name':
'Lovely',
'last_name':
'Spam'})
writer.writerow({
'first_name':
'Wonderful',
'last_name':
'Spam'})
|
有关csv库的一些操作可以参考读写CSV数据一文。
CSV模块操作示例
输入文件:stocks.csv
1
2
3
4
5
6
7
|
Symbol,Price,Date,Time,Change,Volume
"AA",
39.48,
"6/11/2007",
"9:36am",
-0.18,
181800
"AIG",
71.38,
"6/11/2007",
"9:36am",
-0.15,
195500
"AXP",
62.58,
"6/11/2007",
"9:36am",
-0.46,
935000
"BA",
98.31,
"6/11/2007",
"9:36am",+
0.12,
104800
"C",
53.08,
"6/11/2007",
"9:36am",
-0.25,
360900
"CAT",
78.29,
"6/11/2007",
"9:36am",
-0.23,
225400
|
输出文件:dest.csv
1
2
3
4
|
Symbol,Price,Date,Time,Change,Volume
AA,
39.48,
6/
11/
2007,
9:
36am,
-0.18,
181800
AIG,
71.38,
6/
11/
2007,
9:
36am,
-0.15,
195500
AXP,
62.58,
6/
11/
2007,
9:
36am,
-0.46,
935000
|
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
"""
Created on 2015/9/30 14:55
@author: 'WX'
"""
from collections
import namedtuple
import csv
if __name__ ==
"__main__":
fileName =
'stocks.csv'
writeFileName =
'dest.csv'
with open(fileName)
as f:
reader = csv.reader(f)
headers = next(reader)
print(
"使用下标进行访问")
for row
in reader:
length = len(row)
for i
in range(length):
print(row[i], end=
't')
print()
print(
'------------------------------------------------')
with open(fileName)
as f:
reader = csv.reader(f)
headers = next(reader)
Row = namedtuple(
'Row', headers)
print(
"使用命名元组进行访问")
for r
in reader:
row = Row(*r)
line =
'%st%st%st%st%st%s' % (row.Symbol, row.Price, row.Date, row.Time, row.Change, row.Volume)
print(line)
print(
'------------------------------------------------')
with open(fileName)
as f:
dict_reader = csv.DictReader(f)
print(
"使用字典序列进行访问")
for row
in dict_reader:
line =
'%st%st%st%st%st%s' % (
row[
'Symbol'], row[
'Price'], row[
'Date'], row[
'Time'], row[
'Change'], row[
'Volume'])
print(line)
print(
'------------------------------------------------')
print(
"使用元组方式写入,SUCCESS!")
with open(writeFileName, mode=
'w', newline=
'')
as wf:
headers = [
'Symbol',
'Price',
'Date',
'Time',
'Change',
'Volume']
rows = [(
'AA',
39.48,
'6/11/2007',
'9:36am',
-0.18,
181800),
(
'AIG',
71.38,
'6/11/2007',
'9:36am',
-0.15,
195500),
(
'AXP',
62.58,
'6/11/2007',
'9:36am',
-0.46,
935000),
]
writer = csv.writer(wf)
writer.writerow(headers)
writer.writerows(rows)
print(
"使用字典方式写入,SUCCESS!")
with open(writeFileName, mode=
'w', newline=
'')
as wf:
headers = [
'Symbol',
'Price',
'Date',
'Time',
'Change',
'Volume']
rows = [{
'Symbol':
'AA',
'Price':
39.48,
'Date':
'6/11/2007',
'Time':
'9:36am',
'Change':
-0.18,
'Volume':
181800},
{
'Symbol':
'AIG',
'Price':
71.38,
'Date':
'6/11/2007',
'Time':
'9:36am',
'Change':
-0.15,
'Volume':
195500},
{
'Symbol':
'AXP',
'Price':
62.58,
'Date':
'6/11/2007',
'Time':
'9:36am',
'Change':
-0.46,
'Volume':
935000}, ]
writer = csv.DictWriter(wf, headers)
writer.writeheader()
writer.writerows(rows)
with open(writeFileName, mode=
'w', newline=
'')
as wf:
headers = [
'Symbol',
'Price',
'Date',
'Time',
'Change',
'Volume']
rows = [(
'AA',
39.48,
'6/11/2007',
'9:36am',
-0.18,
181800),
(
'AIG',
71.38,
'6/11/2007',
'9:36am',
-0.15,
195500),
(
'AXP',
62.58,
'6/11/2007',
'9:36am',
-0.46,
935000),
]
writer = csv.writer(wf, delimiter=
';')
writer.writerow(headers)
writer.writerows(rows)
print(
"使用分好作为分隔符写入,SUCCESS!")
|
控制台输出
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
|
C:Python34python.exe E:/workspaces/Python3/edu/shu/python/shumo/CsvUtil.py
使用下标进行访问
AA
39.48
6/
11/
2007
9:
36am
-0.18
181800
AIG
71.38
6/
11/
2007
9:
36am
-0.15
195500
AXP
62.58
6/
11/
2007
9:
36am
-0.46
935000
BA
98.31
6/
11/
2007
9:
36am +
0.12
104800
C
53.08
6/
11/
2007
9:
36am
-0.25
360900
CAT
78.29
6/
11/
2007
9:
36am
-0.23
225400
------------------------------------------------
使用命名元组进行访问
AA
39.48
6/
11/
2007
9:
36am
-0.18
181800
AIG
71.38
6/
11/
2007
9:
36am
-0.15
195500
AXP
62.58
6/
11/
2007
9:
36am
-0.46
935000
BA
98.31
6/
11/
2007
9:
36am +
0.12
104800
C
53.08
6/
11/
2007
9:
36am
-0.25
360900
CAT
78.29
6/
11/
2007
9:
36am
-0.23
225400
------------------------------------------------
使用字典序列进行访问
AA
39.48
6/
11/
2007
9:
36am
-0.18
181800
AIG
71.38
6/
11/
2007
9:
36am
-0.15
195500
AXP
62.58
6/
11/
2007
9:
36am
-0.46
935000
BA
98.31
6/
11/
2007
9:
36am +
0.12
104800
C
53.08
6/
11/
2007
9:
36am
-0.25
360900
CAT
78.29
6/
11/
2007
9:
36am
-0.23
225400
------------------------------------------------
使用元组方式写入,SUCCESS!
使用字典方式写入,SUCCESS!
Process finished
with exit code
0
|
最后,如果你读取CSV数据的目的是做数据分析和统计的话,你可能需要看一看Pandas包。Pandas包含了一个非常方便的函数叫pandas.read_csv(),它可以加载CSV数据到一个DataFrame对象中去。然后利用这个对象你就可以生成各种形式的统计、过滤数据以及执行其他高级操作了。
matplotlib
matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中。
matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表。
一个matplotlib绘图的示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import numpy
as np
import matplotlib.pyplot
as plt
x = np.linspace(
0,
10,
1000)
y = np.sin(x)
z = np.cos(x**
2)
plt.figure(figsize=(
8,
4))
plt.plot(x,y,label=
"$sin(x)$",color=
"red",linewidth=
2)
plt.plot(x,z,
"b--",label=
"$cos(x^2)$")
plt.xlabel(
"Time(s)")
plt.ylabel(
"Volt")
plt.title(
"PyPlot First Example")
plt.ylim(
-1.2,
1.2)
plt.legend()
plt.show()
|
从上面,我们能看到matplotlib绘图模块的几个重要部分,分别是plt.figure
、plt.plot
、plt.xlabel
、plt.ylabel
、plt.title
、plt.xlim
、plt.ylim
、plt.legnd
、plt.show
等。此外还包括plt.savefig
、plt.axes
figure
函数的作用是创建一个绘图对象,并且使它成为当前的绘图对象,也可以不创建绘图对象直接调用接下来的plot函数直接绘图,matplotlib会为我们自动创建一个绘图对象。如果需要同时绘制多幅图表的话,可以是给figure传递一个整数参数指定图标的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。
figure(figsize=(8,6), dpi=80)
,这句的功能是“创建一个 8 6 点(point)的图,并设置分辨率为 80”。通过figsize参数可以指定绘图对象的宽度和高度,单位为英寸;dpi参数指定绘图对象的分辨率,即每英寸多少个像素,默认值为80。因此本例中所创建的图表窗口的宽度为880 = 640像素,高度则为6*80=480像素。
除了设置图片像素和分辨率之外,还可以设置保存图片的像素和分辨率,通过savefig函数实现,这点会在之后阐述。
plot
plot函数是直接的绘图部分,plt.plot
后参数包括以下内容:
- x y函数/取值,如果为数组则需要转为向量形式,允许 x1,y1,x2,y2在同一张图中绘制多个图像(也可调用两次plot函数)
- 格式化参数,其包括了color/style等样式,指定线条的颜色样式等。采用格式化参数可快速指定线条样式。具体样式会在下面阐述
- linewidth,指定曲线的宽度
- label值:指所绘制曲线的对应名称,此部分在
plt.legend
中显示。字符串前后添加”$”符号,会显示为其latex格式的数学公式
格式化参数部分,包括颜色、线条标记、线条属性三部分。参数分别为color
、marker
、linestyle
,也可单独设置各参数。
线条颜色
标记 |
描述 |
b |
蓝色 |
g |
绿色 |
r |
红色 |
c |
青色 |
m |
洋红色 |
y |
黄色 |
k |
黑色 |
w |
白色 |
以上是常用颜色,当需要使用其他颜色时,也可以使用HTML十六进制字符串 color=’#eeefff’来调用颜色
线条属性
标记 |
描述 |
- |
实线 |
– |
破折线 |
-. |
点划线 |
: |
虚线 |
. |
点标记 |
, |
像素标记 |
线条标记
标记 |
描述 |
o |
圆圈 |
v |
倒三角 |
^ |
正三角 |
< |
左转90度的三角形 |
> |
右转90度的三角形 |
1 |
禾苗形状1 |
2 |
禾苗形状2 |
3 |
禾苗形状3 |
4 |
禾苗形状4 |
s |
正方形 |
p |
五边形 |
* |
*标记 |
h |
六边形1 |
H |
六边形2 |
+ |
+标记 |
x |
x标记 |
D |
菱形 |
d |
小菱形 |
|
|
竖线 |
_ |
水平线 |
需要注意的是,当有线条标记这个属性时,即使添加了线条属性这部分,也只会在对应的函数值处展示线条标记,连续的线条样式跟随线条属性而不跟随线条标记。
基本配置
采用matplotlib绘图时,有一些基本配置信息。
plt.xlabel
:x轴坐标
plt.ylabel
:y轴坐标
plt.title
:图表名称
plt.xlim
:x轴范围
plt.ylim
:y轴范围
plt.legend
:显示图例
图例legend的用法为legend(loc='upper left')
。除了图例之外,还可以直接将曲线代表的函数绘制在曲线旁边,所用的函数为text
函数。用法为text(1, 7.5, r'$10^x$', fontsize=16)
,即text(x_zuobiao, y_zuobiao, biaodashi, fontsize)
。当然还有annotate
用法,此处不展开描述。
。
其中,x/y周坐标范围也可用plt.axis([-0.1, 4.5, -0.1, 4.5])
形式来表示。
以上绘制图表完毕后,可采用ply.show()
来显示图表。同时也可以采用savefig("test.png",dpi=72)
来保存图表,可设置保存的图表像素大小。
除了上述之外,还包括一些细节设置方面,如x/y轴的刻度间距等。
刻度间距可通过下述来设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
xlim(
-4.0,
4.0)
xticks(np.linspace(
-4,
4,
9,endpoint=
True))
ylim(
-1.0,
1.0)
yticks(np.linspace(
-1,
1,
5,endpoint=
True))
xticks( [-np.pi, -np.pi/
2,
0, np.pi/
2, np.pi])
yticks([
-1,
0, +
1])
xticks([-np.pi, -np.pi/
2,
0, np.pi/
2, np.pi],
[
r'$-pi$',
r'$-pi/2$',
r'$0$',
r'$+pi/2$',
r'$+pi$'])
yticks([
-1,
0, +
1],
[
r'$-1$',
r'$0$',
r'$+1$'])
|
子图 subplot
当涉及到绘出多个图像时,除了采用多次plot将图像绘在同一张表中,还可以采用子图形式。利用subplot分配图表位置(依次排序)和采用的图表,进行绘图。subplot(221),表示分成2行2列,当前采用的是第一个图表。当各参数都小于10时,可简写为221形式,超过时需要表示为(2,2,1)形式。
对于多子图的绘图,每个子图绘制完毕之后再绘制下一个子图。即:
1
2
3
4
5
|
plt.subplot(
211)
plt.plot(x,y)
plt.subplot(
212)
plt.plot(x,y)
|
显示中文
matplotlib的缺省配置文件中所使用的字体无法正确显示中文。为了让图表能正确显示中文,可以有几种解决方案。
- 在程序中直接指定字体
- 在程序开头修改配置字典rcParams
- 修改配置文件
下面是通过修改字体实现的一种方法
1
2
3
4
5
6
7
8
9
10
11
12
|
from matplotlib.font_manager
import FontProperties
import matplotlib.pyplot
as plt
import numpy
as np
font = FontProperties(fname=
r"c:windowsfontssimsun.ttc", size=
14)
t = np.linspace(
0,
10,
1000)
y = np.sin(t)
plt.plot(t, y)
plt.xlabel(
u"时间", fontproperties=font)
plt.ylabel(
u"振幅", fontproperties=font)
plt.title(
u"正弦波", fontproperties=font)
plt.show()
|
绘图示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from matplotlib.matlab
import *
def f(x, c):
m1 = sin(
2*pi*x)
m2 = exp(-c*x)
return multiply(m1, m2)
x = linspace(
0,
4,
100)
sigma =
0.5
plot(x, f(x, sigma),
'r', linewidth=
2)
xlabel(
r'$rm{time} t$', fontsize=
16)
ylabel(
r'$rm{Amplitude} f(x)$', fontsize=
16)
title(
r'$f(x) rm{is damping with} x$', fontsize=
16)
text(
2.0,
0.5,
r'$f(x) = rm{sin}(2 pi x^2) e^{sigma x}$', fontsize=
20)
savefig(
'latex.png', dpi=
75)
show()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import matplotlib.pyplot
as plt
plt.figure(
1)
plt.subplot(
211)
plt.plot([
1,
2,
3])
plt.subplot(
212)
plt.plot([
4,
5,
6])
plt.figure(
2)
plt.plot([
4,
5,
6])
plt.figure(
1)
plt.subplot(
211)
plt.title(
'Easy as 1,2,3')
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from matplotlib.matlab
import *
filename =
"d:\wei\exp\current.dat"
X = load(filename)
dp = X[:,
0]
i_mea = X[:,
1]
i_mea_err = X[:,
2]
i_cal = X[:,
3]
i_cal_err = X[:,
4]
width =
3
h1 = bar(dp, i_mea, width, color=
'r', yerr=i_mea_err)
h2 = bar(dp+width, i_cal, width, color=
'b', yerr=i_cal_err)
xlabel(
'Particle diameter (nm)', fontsize=
16)
xticks(dp+width, dp)
ylabel(
'Signal current (nA)', fontsize=
16)
title(
'Measured current vs. calculated current')
legend((h1[
0], h2[
0]), (
'measured current',
'calculated current'), loc=
2)
savefig(
'current.png', dpi=
75)
show()
|
1
2
3
4
5
6
7
8
|
import numpy
as np
import matplot.pyplot
as plt
x = np.random.randn(
1000)
plt.hist(x,
50)
plt.show()
|
直方图是 Matplotlib 中最简单的图形之一。你只需要给 hist() 函数传入一个包含数据的数组。第二个参数代表数据容器的个数。数据容器代表不同的值的间隔,并用来包含我们的数据。数据容器越多,图形上的数据条就越多。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import numpy
as np
import matplotlib.pyplot
as plt
ax = plt.subplot(
111)
t = np.arange(
0.0,
5.0,
0.01)
s = np.cos(
2*np.pi*t)
line = plt.plot(t, s, lw=
2)
plt.annotate(
'local max', xy=(
2,
1), xytext=(
3,
1.5),
arrowprops=dict(facecolor=
'black', shrink=
0.05))
plt.ylim(
-2,
2)
plt.show()
|
参见Matplotlib 教程