继续学习~这次是模块相关的知识。
这里会总结下模块的概念,并且不断将用到的一些第三方模块补充到这里,便于以后查用。
1. 模块的基本概念
一个.py就称为一个模块(Module)。
不同模块可以有相同的函数名和变量名,不过最好不要用系统内置的函数名。
不同人编写的模块名字可能会冲突,这时候可以使用包(Package)来解决。不同包名下的模块不会冲突。
新建一个文件夹作为包,文件夹的名字就是包名,然后把python文件放到文件夹内,这样模块的名字就变为了“文件夹名.文件名”。另外,每个包目录下会有个__init__.py文件,可以为空文件,用来表明这个文件夹是一个包。包是可以有多级的,每层目录下面都要有__init__.py文件。
2. 使用模块
下面以一个简单的例子来说明如何使用模块:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = 'Michael Liao'
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
test()
第1行和第2行是标准注释,第1行可以让这个文件在Unix/Linux/Mac上运行,第2行表示这个文件本身使用UTF-8编码;
第4行是一个字符串,表示模块的文档注释,任何模块的第一个字符串都被视为模块的文档注释;
第6行使用__author__变量表示作者的名字。
接下来是程序的正文,为了使用内置的sys模块,首先需要引入,这样后,就有了变量sys指向该模块。
还有一种引入方式类似from sys import argv来直接引入模块中的成员,这样被引入的成员可以直接使用而不需要在前面加上模块名(如果想引入所有可以使用*替代)。不过这种方式不是很推荐,可能会降低代码的易读性,并且代码命名的冲突。
sys模块有一个argv变量,用list存储了命令行的所有参数,list中第一个元素是模块名。
在命令行运行这个模块时,Python解释器把特殊变量__name__置为__main__,而最后这两行代码正好起到了作用,使程序可以直接执行。
但是在其他地方导入该模块时,不会设置这个__name__变量,需要手动调用。
3. 安装第三方模块
可以通过pip命令来安装第三方模块,也可以下载包手动安装。
使用pip命令的安装方法是执行:
pip install
使用手动安装方式是在包目录下执行:
python setup.py install
第三方库一般都会在Python官方网站https://pypi.python.org/注册,可以在上面查看和搜索。
加载模块会从sys.path变量中存放的路径中获取,如果要添加自己的搜索路径,有两种办法:
直接修改sys.path,仅运行时有效;
设置环境变量PYTHONPATH,把自己的搜索路径加进来(类似于PATH环境变量,但不需要加Python本身的,只需要加自己的)。
4. 常用的内建模块
datetime
from datetime import datetime引入datetime模块中的datetime类。
datetime.now()获取当前时间。
datetime(2016, 11, 8, 0, 15, 0)创建指定日期时间的datetime。
datetime对象的timestamp()方法可以将datetime转换为timestamp。(Python的timestamp为浮点数,小数位表示毫秒数,乘以1000即与Java中表示相同)
datetime.fromtimestamp()方法可以将timestamp转换为datetime,对应时区为操作系统时区。
datetime.utcfromtimestamp()方法可以将timestamp转换为datetime,对应时区为UTC标准时区。
datetime.strptime()可以将字符串转换为datetime,没有时区信息。格式的详细说明可以参见官方文档。
datetime对象的strftime()方法可以将datetime转换为字符串。
from datetime import timedelta引入datetime模块中的timedelta类。
datetime的加减可以直接使用运算符,加数/减数使用timedelta,可以指定days、hours等参数。
from datetime import timezone引入datetime模块中的timezone类。
datetime类有一个时区属性tzinfo,默认为None,可强制设置时区:
tz_utc_8 = timezone(timedelta(hours=8))
now = datetime.now()
now.replace(tzinfo=tz_utc_8)
可以通过datetimed.utcnow()获取当前的UTC时间,强制设置时区(tzinfo=timezone.utc),再使用astimezone()方法转换到任意时区。
timestamp与时区无关,存储时最好使用timestamp存储。
collections
collections是Python内建的一个集合模块。
namedtuple是一个函数,用于创建一个自定义的tuple对象,并规定tuple元素的个数,可以用属性名来引用其中的某个元素,如:
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
p.x
deque是双向列表,支持append()、pop()和appendleft()、popleft()操作。
defaultdict可以在key不存在时返回一个默认值,而非抛出KeyError,写法如下:
dd = defaultdict(lambda: 'N/A')
OrderedDict可以保序(插入的顺序),可以用来实现一个FIFO的dict,当容量超出限制时,删除最早的key。
Counter是一个简单的计数器,可以用来统计字符串中每个字符出现的次数,是dict的子类。
base64
base64是一种用64个字符来表示任意二进制数据的方法,常用于URL、Cookie、网页中传输少量二进制数据。
关于具体的说明可以直接看廖雪峰老师的讲解:
struct
在Python中,要把一个32位无符号整数变成字节(也就是4个长度的bytes),需要这么写:
>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'
非常麻烦,而且对浮点数无能为力。
好在Python提供了一个struct模块来解决bytes和其他二进制数据类型的转换。
pack()函数把任意数据类型变成bytes;unpack函数把bytes变成指定的数据类型。
第一个参数是处理指令,如'>IH',其中>表示big-endian,I表示4字节无符号整数,H表示2字节无符号整数,具体可参见官方文档。
hashlib
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等。
使用方法类似,以md5举例:
import hashlib
md5 = hashlib.md5()
md5.update('first line'.encode('utf-8'))
md5.update('second line'.encode('utf-8'))
print(md5.hexdigest())
支持分块调用update,和一次调用的结果是一样的。
在应用中,为了防止破解,通常会加上一个复杂字符串,俗称“加盐”;在某些场景下,为了避免不同信息相同数据得到同样的摘要,还会加上信息中固定的字段一起做摘要(如密码加上用户名进行摘要)。
itertools
Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。
count()函数会创建一个无限的迭代器,打印出自然数序列。(不带参数默认是0)
cycle()函数会把传入的序列无限重复下去。(字符串也是序列的一种)
repeat()函数会把一个元素无限的重复下去,可以通过第二个参数指定重复的次数。
通常会通过takewhile()等函数根据条件(第一个参数是lambda表达式,第二个参数是无限序列)来截取一个有限序列。
chain()函数把一组迭代对象串起来,形成一个更大的迭代器。
groupby()函数把迭代器中相邻的重复元素挑出来放在一起,挑选规则是通过函数完成的,可以在第二个参数使用lambda表达式指定规则。
TO BE CONTINUED
5. 常用的第三方库
TO BE CONTINUED...