Base64 | 一种用64个字符来表示任意二进制数据的方法 |
collections |
提供了许多有用的集合类 |
copy |
定义用于复制对象的通用函数。 |
functools |
提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数 |
heapq |
提供基于堆的优先级队列函数 |
os |
提供对与操作系统交互的支持。 |
random |
提供随机数生成。 |
sys |
提供与Python解释器的额外交互级别。 |
time、datetime |
处理日期和时间的标准库 |
工作路径 | os.getcwd() |
返回表示当前工作目录的字符串 |
os.getcwd() # 'C:\\Python34' |
os.chdir(path) |
将当前工作目录更改为path |
os.chdir('C:\\Windows\\System32') os.getcwd() # 'C:\\Windows\\System32' |
|
绝对路径 | os.path.abspath(path) |
返回参数的绝对路径的字符串 |
os.path.abspath('.') # 'C:\\Python34' os.path.abspath('.\\Scripts') # 'C:\\Python34\\Scripts' |
os.path.isabs(path) |
返回 True,如果参数是一个绝对路径 |
os.path.isabs('.') # False os.path.isabs(os.path.abspath('.')) # True |
|
os.path.relpath(path, start) |
返回从 start到 path 的相对路径的字符串;如果没有提供 start,就使用当前工作目录作为开始路径 |
os.path.relpath('C:\\Windows', 'C:\\') # 'Windows' | |
相对路径 | os.path.join(dirname, filename) | 用于路径拼接; Windows上使用反斜杠(\)来构造文件路径,Linux和Mac上使用正斜杠(/)来构造文件路径。os.path.join知道如何处理这一差异, 能够识别当前运行的操作系统,据此选择适合的连接。 |
os.path.join('C','system') #'C\\system' |
路径处理 | os.path.dirname(path) |
返回一个字符串,它包含 path 参数中最后一个斜杠之前的所有内容 |
path = 'C:\\Windows\\System32\\calc.exe' os.path.basename(path) #'calc.exe' |
os.path.basename(path) |
返回一个字符串,它包含 path 参数中最后一个斜杠之后的所有内容 |
os.path.dirname(path) # 'C:\\Windows\\System32' | |
os.path.split(path) |
返回上述两个字符串的元组 |
os.path.split(path )# ('C:\\Windows\\System32', calc.exe') |
|
文件属性 | os.path.getsize(path) |
返回 path 参数中文件的字节数 |
os.path.getsize('C:\\Windows\\System32\\calc.exe') # 776192 |
os.listdir(path) |
返回文件名字符串的列表,包含 path 参数中的每个文件 |
os.listdir('C:\\Windows\\System32') | |
os.path.exists(path) |
path 参数所指的文件或文件夹是否存在 |
||
os.path.isfile(path) |
path 参数存在是否是一个文件 |
||
os.path.isdir(path) |
path 参数存在是否是一个文件夹 |
||
os.rename(src,dst) | 命名文件或目录 | os.rename("text1","text2") | |
文件目录 | os.makedir() |
创建一个名为path的文件夹 |
os.makedir('C:\\delicious') # 创建新文件夹 |
os.walk() | 在目录树中游走输出在目录中的文件名 | for (dirname, dirs, files) in os.walk('.'):
|
import os
count = 0
for (dirname, dirs, files) in os.walk('.'):
for filename in files:
if filename.endswith('.txt') :
thefile = os.path.join(dirname, filename) # 目录中的文件名与目录名连接在一起
print(os.path.getsize(thefile), thefile)
count = count + 1
fhand = open(thefile, 'r')
lines = list()
for line in fhand:
lines.append(line)
if len(lines) == 3 and lines[2].startswith('Sent from my iPhone'): #第三行以Sent开头。
os.remove(thefile)
continue
print('Files:', count)
import os
import re
def rename_files():
file_list = os.listdir(r'C:\Users\linlinle\Downloads\prank')
saved_path = os.getcwd()
os.chdir(r'C:\Users\linlinle\Downloads\prank')
for file_name in file_list:
os.rename(file_name,re.sub(r'([\d]+)','',file_name))
os.chdir(saved_path)
seed(hashable) |
根据参数的散列值初始化随机数生成器,相同散列值具有相同随机生成器(次序一样) |
random.seed(123) random.random() #0.052363598850944326 random.seed(321) random.random() #0.2754594638268887 random.seed(123) random.random() #0.052363598850944326 |
random() |
返回随机生成的一个实数,它在[0,1)区间中的随机浮点值。 |
random.random() # 0.10597640938495168 |
randint(a,b) |
返回闭区间[a,b]中的随机整数。 |
random.randint(1,10) # 2 |
uniform(x,y) | 随机生成下一个实数,它在 [x, y) 范围内 | random.uniform(3,5) #3.31932479344394 |
randrange(start, stop, step) |
返回由参数指示范围中的伪随机数。 |
random.randrange(1,10,5) #6 |
choice(seqence) |
返回所选的伪随机序列的元素。 |
random.choice([3,4,5]) #4 |
shuffle(seqence) |
伪随机地重新排序给定序列的元素。 |
a = [3,4,5] random.shuffle(a) # a : [5,3,4] |
int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换,但int()函数还提供额外的base参数(默认值为10)。如果传入base参数,就可以做N进制的转换:
int('12345', base=8) # 5349
int('12345', 16) # 74565
假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:
def int2(x, base=2):
return int(x, base)
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
import functools
int2 = functools.partial(int, base=2)
int2('1000000') # 64
int2('1010101') # 85
所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
namedtuple
可以很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用其中元素。我们知道tuple
可以表示不变集合,但是,看到(1, 2)
,很难看出这个tuple
是用来表示一个坐标的。定义一个class又小题大做了:
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])#自定义的tuple对象
p = Point(1, 2)
p.x #1 #并可以用属性而不是索引来引用tuple的某个元素
p.y #2
isinstance(p, Point) #True
isinstance(p, tuple) #True
类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple
定义:
# namedtuple('名称', [属性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈。deque
除了实现list的append()
和pop()
外,还支持appendleft()
和popleft()
,这样就可以非常高效地往头部添加或删除元素
from collections import deque
q = deque(['a', 'b', 'c'])
q.append('x')
q.appendleft('y')
q #deque(['y', 'a', 'b', 'c', 'x'])
d.insert() | 指定位置插入 |
d.append('a') | 在最右边添加一个元素 |
d.appendleft('b') | 在最左边添加一个元素 |
d.extend(['c','d']) | 在最右边添加所有元素 |
d.extendleft(['e','f']) | 在最左边添加所有元素 |
d.pop() | 将最右边的元素取出 |
d.popleft() | 将最左边的元素取出 |
d.rotate(-2) | 向左旋转两个位置(正数则向右旋转) |
d.count('a') | 队列中'a'的个数 |
d.remove('c') | 从队列中将'c'删除 |
d.reverse() | 将队列倒序 |
deque的旋转来解决约瑟夫问题
""" 约瑟夫算法
据说著名犹太历史学家 Josephus 有过以下的故事:
在罗马人占领桥塔帕特后,39个犹太人与 Josephus 及他的朋友躲到一个洞中,
39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,
由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,
直到所有人都自杀身亡为止。然而 Josephus 和他的朋友并不想自杀,
问他俩安排的哪两个位置可以逃过这场死亡游戏?
"""
import collections
def ysf(a, b):
d = collections.deque(range(1, a+1)) # 将每个人依次编号,放入到队列中
while d:
d.rotate(-b) # 队列向左旋转b步
print(d.pop()) # 将最右边的删除,即自杀的人
if __name__ == '__main__':
ysf(41,3) # 输出的是自杀的顺序。最后两个是16和31,说明这两个位置可以保证他俩的安全。
使用dict
时,如果引用的Key不存在,就会抛出KeyError
。如果希望key不存在时,返回一个默认值,就可以用defaultdict。
注意默认值是调用函数返回的,而函数在创建defaultdict
对象时传入。除了在Key不存在时返回默认值,defaultdict
的其他行为跟dict
是完全一样的。
from collections import defaultdict
dd = defaultdict(lambda: 'N/A')
dd['key1'] = 'abc'
dd['key1'] # key1存在 :'abc'
dd['key2'] # key2不存在,返回默认值 :'N/A'
使用dict
时,Key是无序的。在对dict
做迭代时,我们无法确定Key的顺序。如果要保持Key的顺序,可以用OrderedDict,
注意,OrderedDict
的Key会按照插入的顺序排列,不是Key本身排序
from collections import OrderedDict
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
od.keys() # 按照插入的Key的顺序返回 ['z', 'y', 'x']
Counter
是一个简单的计数器,例如统计字符出现的个数,Counter
实际上也是dict
的一个子类
from collections import Counter
c = Counter('programming') #Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})
时间间隔是以秒为单位的浮点小数。每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。
timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00
# 对应的北京时间是:
timestamp = 0 = 1970-1-1 08:00:00 UTC+8:00
import time
ticks =time.time() #1541407887.3429832
时间元组
Python函数用一个元组装起来的9组数字处理时间:
序号 | 属性 | 值 |
---|---|---|
0 | tm_year | 2008 |
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 (60或61 是闰秒) |
6 | tm_wday | 0到6 (0是周一) |
7 | tm_yday | 1 到 366(儒略历) |
8 | tm_isdst | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
从返回浮点数的时间戳方式向时间元组转换,只要将浮点数传递给如localtime之类的函数
localtime = time.localtime(time.time())
# time.struct_time(tm_year=2018, tm_mon=11, tm_mday=5, tm_hour=16, tm_min=54, tm_sec=26, tm_wday=0, tm_yday=309, tm_isdst=0)
可以根据需求选取各种格式,但是最简单的获取可读的时间模式的函数是asctime():
localtime = time.asctime( time.localtime(time.time()) )
# 'Mon Nov 5 16:56:09 2018'
可以使用 time 模块的 strftime 方法来格式化日期:
# 格式化成2018-11-05 16:58:30形式
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
# 格式化成'Mon Nov 05 16:58:54 2018'形式
time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())
# 将格式字符串转换为时间戳1541408334.0
a = "Mon Nov 05 16:58:54 2018"
time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y"))
%Y | 四位数的年份表示(0000-9999),%y 两位数的年份表示(00-99) |
%m | 月份(01-12) |
%d | 月内中的一天(0-31) |
%H | 24小时制小时数(0-23) |
%I | 12小时制小时数(01-12) |
%M | 分钟数(00-59) |
%S | 秒(00-59) |
%A | 本地完整星期名称;%a 本地简化星期名称 |
%B | 本地完整的月份名称;%b 本地简化的月份名称 |
%j | 年内的一天(001-366) |
%p | 本地A.M.或P.M.的等价符 |
%U | 一年中的星期数(00-53)星期天为星期的开始 |
%w | 星期(0-6),星期天为星期的开始 |
%W | 一年中的星期数(00-53)星期一为星期的开始 |
%x | 本地相应的日期表示'月/日/二位年' |
%X | 本地相应的时间表示'时:分:秒' |
%z | 当前时区的名称 |
Time 模块包含了以下内置函数,既有时间处理的,也有转换时间格式的:
1 | time.altzone 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。 |
2 | time.asctime([tupletime]) 接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。 |
3 | time.clock( ) 用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。 |
4 | time.ctime([secs]) 作用相当于asctime(localtime(secs)),未给参数相当于asctime() |
5 | time.gmtime([secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0 |
6 | time.localtime([secs]) 接收时间戳(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。 |
7 | time.mktime(tupletime) 接受时间元组并返回时间戳(1970纪元后经过的浮点秒数)。 |
8 | time.sleep(secs) 推迟调用线程的运行,secs指秒数。 |
9 | time.strftime(fmt[,tupletime]) 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。 |
10 | time.strptime(str,fmt='%a %b %d %H:%M:%S %Y') 根据fmt的格式把一个时间字符串解析为时间元组。 |
11 | time.time( ) 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。 |
12 | time.tzset() 根据环境变量TZ重新初始化时间相关设置。 |
Time模块包含了以下2个非常重要的属性:
1 | time.timezone 属性time.timezone是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0大部分欧洲,亚洲,非洲)。 |
2 | time.tzname 属性time.tzname包含一对根据情况的不同而不同的字符串,分别是带夏令时的本地时区名称,和不带的。 |
import datetime
i = datetime.datetime.now()
print ("当前的日期和时间是 %s" % i)
print ("ISO格式的日期和时间是 %s" % i.isoformat() )
print ("当前的年份是 %s" %i.year)
print ("当前的月份是 %s" %i.month)
print ("当前的日期是 %s" %i.day)
print ("dd/mm/yyyy 格式是 %s/%s/%s" % (i.day, i.month, i.year) )
print ("当前小时是 %s" %i.hour)
print ("当前分钟是 %s" %i.minute)
print ("当前秒是 %s" %i.second)
dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
print(dt) #2015-04-19 12:20:00
dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
dt.timestamp() # 把datetime转换为timestamp:1429417200.0
t = 1429417200.0
print(datetime.fromtimestamp(t)) #2015-04-19 12:20:00
cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S') # 2015-06-01 18:19:59
now = datetime.now()
now.strftime('%a, %b %d %H:%M') #'Mon, May 05 16:28'
加减可以直接用+
和-
运算符,不过需要导入timedelta
这个类:
from datetime import datetime, timedelta
now = datetime.now() # datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
now + timedelta(hours=10) #datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
now - timedelta(days=1) #datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
now + timedelta(days=2, hours=12) #datetime.datetime(2015, 5, 21, 4, 57, 3, 540997
用记事本打开exe
、jpg
、pdf
这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。Base64是一种最常见的二进制编码方法。Python内置的base64
可以直接进行base64的编解码:
import base64
base64.b64encode(b'binary\x00string') #b'YmluYXJ5AHN0cmluZw=='
base64.b64decode(b'YmluYXJ5AHN0cmluZw==') #b'binary\x00string'
由于标准的Base64编码后可能出现字符+
和/
,在URL中就不能直接作为参数,所以又有一种"url safe"的base64编码,其实就是把字符+
和/
分别变成-
和_
:
base64.b64encode(b'i\xb7\x1d\xfb\xef\xff') #b'abcd++//'
base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff') #b'abcd--__'
base64.urlsafe_b64decode('abcd--__') #b'i\xb7\x1d\xfb\xef\xff'
Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
import copy
dic = {"cpu":[80,]}
print(dic) #{'cpu': [80]}
new_dic = copy.copy(dic)
new_dic['cpu'][0] = 50
print(dic) #{'cpu': [50]}
print(new_dic) #{'cpu': [50]}
import copy
dic = {"cpu":[80,]}
print(dic) #{'cpu': [80]}
new_dic = copy.deepcopy(dic)
new_dic['cpu'][0] = 50
print(dic) #{'cpu': [80]}
print(new_dic) #{'cpu': [50]}
区别:浅复制会造成某个对象中的列表部分改变会牵动另一个对象的相应改变;而深复制两者完全独立。
heapq.heappush(heap, item) | 将item,推入heap | h = [11,10,9] heapq.heappush(h,8) # h = [11,10,9,8] |
heapq. heapify (x) |
|
h = [11,10,9,8] heapq.heappush(h,1)#[1, 11, 9, 8, 10] heapq.heapify(h)# 堆初始化 h #[1, 8, 9, 11, 10] |
heapq. heappop (heap) |
弹出并返回最小级别的item,若要在不弹出的情况下访问最小项,请使用heap[0]。 | heapq.heappop(h)#1 h[0]#8 h #[8, 10, 9, 11] |
heapq. heappushpop (heap, item) |
将item压入栈中,然后返回并弹出最小级别的item,组合操作比push和pop分开操作更有效 | heapq.heappushpop(h,100)#8 h # [9, 10, 100, 11] |
heapq. heapreplace (heap, item) |
弹出并返回最小值,然后推入item,heap的size不变 |
h#[1, 10, 100, 11] |
heapq. merge (*iterables, key=None, reverse=False) |
将多个排序输入合并为一个排序输出,并返回一个iterator | h1=[1,3,5] h_m=heapq.merge(h,h1) h_m #generator object:[1,1,3,5,10,100,11] |
heapq. nsmallest (n, iterable, key=None) |
返回item中大到小顺序的前N个元素 | itemsDict=[ {'name':'dgb1','age':23,'salary':10000}, {'name':'dgb2','age':23,'salary':15000}, {'name':'dgb3','age':23,'salary':80000}, {'name':'dgb4','age':23,'salary':80000} ] itemsDictlarge = heapq.nlargest(3,itemsDict,lambda s:s['salary']) itemsDictlarge #[{'name': 'dgb3', 'age': 23, 'salary': 80000}, # {'name': 'dgb4', 'age': 23, 'salary': 80000}, #{'name': 'dgb2', 'age': 23, 'salary': 15000}] |
heapq. nsmallest (n, iterable, key=None) |
返回item中小到大顺序的前N个元素 | itemsDictlarge = heapq.nsmallest(3,itemsDict,lambdas:s['salary']) #[{'age': 23, 'salary': 10000, 'name': 'dgb1'}, #{'age': 23, 'salary': 15000, 'name': 'dgb2'}, #{'age': 23, 'salary': 80000, 'name': 'dgb3'}] |
sys.argv 命令行参数List,第一个元素是程序本身路径;类似于shell的位置参数
sys.argv[0] 表示程序自身
sys.argv[1] 表示程序的第一个参数
sys.argv[2] 表示程序的第二个参数
import sys
print(sys.argv[0])
print(sys.argv[1])
print(sys.argv[2])
"""
以上实例输出结果:python ye.py test test1
ye.py
test
test1
"""
sys.exit(n) 退出程序,正常退出时exit(0)
import sys
a=2
if a<=2:
sys.exit(8)
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
print(sys.path)
sys.path.apend 临时添加环境变量
sys.path.append('你的模块路径')
以计算函数运行时间的装饰器为例,进行模块的部署与安装。首先将decorator_timer.py文件放在一个decorator_timer文件夹内,并新建setup.py文件。
from distutils.core import setup
setup(
name = "decorator_timer",
version = "1.0.0",
py_modules = ["decorator_timer"],
author = "linlinle"
)
依次运行两行命令python setup.py sdist和python setup.py install,现在就可以直接import导入此模块。
D:\Github\Python-learning-notes\Application\Simple_Implementation>python setup.py sdist
running sdist
running check
warning: check: missing required meta-data: url
warning: check: missing meta-data: if 'author' supplied, 'author_email' must be supplied too
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default file list)
warning: sdist: standard file not found: should have one of README, README.txt
writing manifest file 'MANIFEST'
creating decorator_timer-1.0.0
making hard links in decorator_timer-1.0.0...
hard linking decorator_timer.py -> decorator_timer-1.0.0
hard linking setup.py -> decorator_timer-1.0.0
creating 'dist\decorator_timer-1.0.0.zip' and adding 'decorator_timer-1.0.0' to it
adding 'decorator_timer-1.0.0\decorator_timer.py'
adding 'decorator_timer-1.0.0\PKG-INFO'
adding 'decorator_timer-1.0.0\setup.py'
removing 'decorator_timer-1.0.0' (and everything under it)
D:\Github\Python-learning-notes\Application\Simple_Implementation>python setup.py install
running install
running build
running build_py
creating build
creating build\lib
copying decorator_timer.py -> build\lib
running install_lib
copying build\lib\decorator_timer.py -> D:\Program Files\Anaconda3\Lib\site-packages
byte-compiling D:\Program Files\Anaconda3\Lib\site-packages\decorator_timer.py to decorator_timer.cpython-35.pyc
running install_egg_info
Removing D:\Program Files\Anaconda3\Lib\site-packages\decorator_timer-1.0.0-py3.5.egg-info
Writing D:\Program Files\Anaconda3\Lib\site-packages\decorator_timer-1.0.0-py3.5.egg-info
decorator_timer文件夹多出如下内容:
MANIFEST文件:模块分布中所包含的文件列表
build -> lib -> decorator_timer.py文件:新文件夹下的新文件
dist -> decorator_timer-1.0.0.zip: 模块分布的压缩包