Python进阶——time、random、collections、itertools

文章目录

  • Python自身提供了比较丰富的生态,拿来即用,可极大的提高开发效率

第一部分 time库——Python处理时间的标准库

1.1 获取现在时间

time.localtime() 本地时间
time.gmtime() UTC世界统一时间 比北京时间晚8个小时
time.ctime() 返回本地时间的字符串
time.strftime 自定义格式化输出
import time

t_local = time.localtime()
t_UTC = time.gmtime()
print("t_local", t_local)           # 本地时间
print("t_UTC", t_UTC)               # UTC统一时间
print(time.ctime())                 # 返回本地时间的字符串
print(time.strftime("%Y-%m-%d %A %H:%M:%S", t_local))    # 格式化输出
t_local time.struct_time(tm_year=2020, tm_mon=5, tm_mday=4, tm_hour=8, tm_min=26, tm_sec=11, tm_wday=0, tm_yday=125, tm_isdst=0)
t_UTC time.struct_time(tm_year=2020, tm_mon=5, tm_mday=4, tm_hour=0, tm_min=26, tm_sec=11, tm_wday=0, tm_yday=125, tm_isdst=0)
Mon May  4 08:26:11 2020
2020-05-04 Monday 08:26:11

1.2 time.sleep(t) 程序暂停t秒

1.3 时间戳与计时器

time.time() 返回自纪元以来的秒数,记录sleep
time.perf_counter() 随意选取一个时间点,记录现在时间到该时间点的间隔秒数,记录sleep
time.process_time() 随意选取一个时间点,记录现在时间到该时间点的间隔秒数,不记录sleep
  • perf_counter()精度较time()更高一些,但是日常使用time()足够用
  • 同一个程序里面,第一次随意取时间点之后,就都按照这个时间点来取了,两个不同的程序中取的标准点可能是不同的。
import time

t_1_start = time.time()
t_2_start = time.perf_counter()
t_3_start = time.process_time()
print(t_1_start)
print(t_2_start)
print(t_3_start)

res = 0
for i in range(1000000):
    res += i
    
time.sleep(5)
t_1_end = time.time()
t_2_end = time.perf_counter()
t_3_end = time.process_time()

print("time方法:{:.3f}秒".format(t_1_end-t_1_start))
print("perf_counter方法:{:.3f}秒".format(t_2_end-t_2_start))
print("process_time方法:{:.3f}秒".format(t_3_end-t_3_start))
1588551757.182366
10111.7768368
1.609375
time方法:5.097秒
perf_counter方法:5.097秒
process_time方法:0.094秒

第二部分 random库——伪随机数

  • 基本可以用于除加密解密算法这些对随机性要求非常强的算法外的大多数工程应用

2.1 随机种子——seed(a=None)

  • 相同种子会产生相同的随机数
  • 如果不设置随机种子,以系统当前时间为默认值
from random import *
​
seed(10)
print(random())
seed(10)
print(random())
0.5714025946899135
0.5714025946899135
from random import *

print(random())
0.20609823213950174

2.2 产生随机整数

2.2.1 randint(a, b)——产生[a, b]之间的随机整数

from random import *

numbers = [randint(1,10) for i in range(10)]
print(numbers)
[3, 5, 6, 3, 8, 4, 8, 10, 7, 1]

2.2.2 randrange(a, b, step)——产生[a, b)之间指定步长的随机整数

  • 开始值可省,默认0
  • 步长可省,默认1
from random import *

numbers = [randrange(10) for i in range(10)]
print(numbers)

numbers = [randrange(0, 10, 2) for i in range(10)]
print(numbers)
[6, 3, 0, 0, 7, 4, 9, 1, 8, 1]
[2, 6, 8, 4, 8, 2, 0, 0, 6, 2]

2.3 产生随机浮点数

2.3.1 random()——产生[0.0, 1.0)之间的随机浮点数

from random import *

numbers = [random() for i in range(3)]
print(numbers)
[0.45683115105830563, 0.6858614854745947, 0.6618463200523511]

2.3.2 uniform(a, b)——产生[a, b]之间的随机浮点数

from random import *

numbers = [uniform(2.1, 3.5) for i in range(3)]
print(numbers)
[2.286169402597098, 3.1749729395215867, 3.475378548615667]

2.4 序列用函数

2.4.1 choice(seq)——从序列类型中随机返回一个元素

from random import *

print(choice(['win', 'lose', 'draw']))
print(choice("python"))
'draw'
'h'

2.4.2 choices(seq,weights=None, k)——对序列类型进行k次重复采样,可设置权重

from random import *

print(choices(['win', 'lose', 'draw'], k=5))
print(choices(['win', 'lose', 'draw'], [4,4,2], k=10))
['win', 'win', 'draw', 'draw', 'lose']
['draw', 'lose', 'lose', 'draw', 'win', 'lose', 'win', 'lose', 'win', 'lose']

2.4.3 sample(seq, k)——对序列类型进行k次不重复采样

  • k只能取小等于元素个数的值
from random import *

print(sample([10, 20, 30, 40, 50], k=3))
[20, 30, 10]

2.4.4 shuffle(seq)——将序列类型中元素随机排列

from random import *

numbers = ["one", "two", "three", "four"]
shuffle(numbers)
print(numbers)
['four', 'one', 'three', 'two']

2.5 概率分布

gauss(mean, std) 产生一个符合高斯分布的随机数
from random import *

number = gauss(0, 1)
print(number)
0.6331522345532208
  • 多生成几个
from random import *
import matplotlib.pyplot as plt
​
res = [gauss(0, 1) for i in range(100000)]
​
plt.hist(res, bins=1000)    # 绘图
plt.show()

在这里插入图片描述

2.6 几个小例子

2.6.1 用random库实现简单的微信红包分配

import random

​
def red_packet(total, num):
    for i in range(1, num):
        per = random.uniform(0.01, total/(num-i+1)*2)    # 为了公平,要保证每个人获得红包的期望是total/num
        total = total - per                              # uniform是均匀分布,均匀分布的期望是(下限+上限)/2
        print("第{}位红包金额: {:.2f}元".format(i, per)) # 下限0.01约等于0
    else:
        print("第{}位红包金额: {:.2f}元".format(num, total))
            
            
red_packet(10, 5)
第1位红包金额: 1.85元
第2位红包金额: 3.90元
第3位红包金额: 0.41元
第4位红包金额: 3.30元
第5位红包金额: 0.54元
  • 验证一下期望是不是total/num
import random
import numpy as np
​
​
def red_packet(total, num):
    ls = []
    for i in range(1, num):
        per = round(random.uniform(0.01, total/(num-i+1)*2), 2)     # 保证每个人获得红包的期望是total/num
        ls.append(per)
        total = total - per
    else:
        ls.append(total)
        
    return ls
            
            
# 重复发十万次红包,统计每个位置的平均值(约等于期望)
res = []
for i in range(100000):
    ls = red_packet(10,5)
    res.append(ls)
​
res = np.array(res)
print(res[:5])
print(np.mean(res, axis=0))
[[1.71 1.57 0.36 1.25 5.11]
 [1.96 0.85 1.46 3.29 2.44]
 [3.34 0.27 1.9  0.64 3.85]
 [1.99 1.08 3.86 1.69 1.38]
 [2.43 0.16 0.11 0.79 6.51]]
array([1.9991849, 2.0055725, 2.0018144, 2.0022472, 1.991181 ])
  • 前面4个人的随机数下限是0.01,期望略大于2,导致最后一个略小,如果设成0,就不存在这个问题了。

2.6.2 产生4位由数字和英文字母构成的验证码

import random
import string
​
print(string.digits)
print(string.ascii_letters)
​
s=string.digits + string.ascii_letters
v=random.sample(s,4)
print(v)
print(''.join(v))
0123456789
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
['n', 'Q', '4', '7']
nQ47

第三部分 collections库——容器数据类型

3.1 namedtuple——具名元组

  • 点的坐标,仅看数据,很难知道表达的是一个点的坐标
p = (1, 2)
  • 构建一个新的元组子类
    定义方法如下:typename 是元组名字,field_names 是域名
collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
调用属性——元组名.属性名
索引——元组名[index]
解包——变量1, 变量2 = 元组名
是元组的子类
import collections

Point = collections.namedtuple("Point", ["x", "y"])
p = Point(1, y=2)
print(p)

# 可以调用属性
print(p.x)
print(p.y)

#有元组的性质
print(p[0])
print(p[1])
x, y = p
print(x)
print(y)

# 确实是元组的子类
print(isinstance(p, tuple))
Point(x=1, y=2)
1
2
1
2
1
2
True
  • 模拟扑克牌
import collections
from random import *

Card = collections.namedtuple("Card", ["rank", "suit"])
ranks = [str(n) for n in range(2, 11)] + list("JQKA")    
suits = "spades diamonds clubs hearts".split()
print("ranks", ranks)
print("suits", suits)
cards = [Card(rank, suit) for rank in ranks
                          for suit in suits]
print(cards[:5])

# 洗牌
shuffle(cards)
print(cards[:5])

# 随机抽一张牌
print(choice(cards))

# 随机抽多张牌
print(sample(cards, k=5))
ranks ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
suits ['spades', 'diamonds', 'clubs', 'hearts']
[Card(rank='2', suit='spades'), Card(rank='2', suit='diamonds'), Card(rank='2', suit='clubs'), Card(rank='2', suit='hearts'), Card(rank='3', suit='spades')]
[Card(rank='K', suit='hearts'), Card(rank='9', suit='hearts'), Card(rank='K', suit='spades'), Card(rank='8', suit='diamonds'), Card(rank='J', suit='diamonds')]
Card(rank='7', suit='diamonds')
[Card(rank='A', suit='clubs'), Card(rank='5', suit='diamonds'), Card(rank='8', suit='hearts'), Card(rank='K', suit='diamonds'), Card(rank='2', suit='hearts')]

3.2 Counter——计数器工具

from collections import Counter

s = "牛奶奶找刘奶奶买牛奶"
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
cnt_str = Counter(s)
cnt_color = Counter(colors)
print(cnt_str)
print(cnt_color)
Counter({'奶': 5, '牛': 2, '找': 1, '刘': 1, '买': 1})
Counter({'blue': 3, 'red': 2, 'green': 1})
是字典的一个子类
from collections import Counter

print(isinstance(Counter(), dict))
True
计数器.most_commom(n)——返回 n 个频率最高的元素和计数
from collections import Counter

colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
cnt_color = Counter(colors)
print(cnt_color.most_common(2))
[('blue', 3), ('red', 2)]
计数器.elements()——元素展开
from collections import Counter

colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
cnt_color = Counter(colors)
print(list(cnt_color.elements()))
['red', 'red', 'blue', 'blue', 'blue', 'green']
计数器±计数器——频数加减
from collections import Counter

c = Counter(a=3, b=1, c=1)
d = Counter(a=1, b=2)
print(c+d)
Counter({'a': 4, 'b': 3, 'c': 1})
  • 【例】从一副牌中抽取10张,大于10的比例有多少
from collections import Counter

cards = collections.Counter(tens=16, low_cards=36)
seen = sample(list(cards.elements()), k=10)
print(seen)

print(seen.count('tens') / 10)
['tens', 'low_cards', 'low_cards', 'low_cards', 'tens', 'tens', 'low_cards', 'low_cards', 'low_cards', 'low_cards']
0.3

3.3 deque——双向队列

  • 列表访问数据非常快速
    插入和删除操作非常慢——通过移动元素位置来实现
    特别是 insert(0, v) 和 pop(0),在列表开始进行的插入和删除操作
  • 双向队列可以方便的在队列两边高效、快速的增加和删除元素
append 右端增加
appendleft 左端增加
pop() 右端删除
popleft() 左端删除
from collections import deque
​
d = deque('cde') 
print(d)

d.append("f")        # 右端增加
d.append("g")
d.appendleft("b")    # 左端增加
d.appendleft("a")
print(d)

d.pop()              # 右端删除 
d.popleft()          # 左端删除
print(d)
deque(['c', 'd', 'e'])
deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
deque(['b', 'c', 'd', 'e', 'f'])
  • deque 其他用法可参考官方文档

第四部分 itertools库——迭代器

4.1 排列组合迭代器

4.1.1 product——笛卡尔积

import itertools
​
for i in itertools.product('ABC', '01'):
    print(i)
('A', '0')
('A', '1')
('B', '0')
('B', '1')
('C', '0')
('C', '1')
import itertools
​
for i in itertools.product('ABC', repeat=2):
    print(i)
('A', 'A')
('A', 'B')
('A', 'C')
('B', 'A')
('B', 'B')
('B', 'C')
('C', 'A')
('C', 'B')
('C', 'C')

4.1.2 permutations——排列

import itertools

for i in itertools.permutations('ABC', 2):   # 2是排列的长度,省略默认全排列
    print(i)
('A', 'B')
('A', 'C')
('B', 'A')
('B', 'C')
('C', 'A')
('C', 'B')

4.1.3 combinations——组合

import itertools

for i in itertools.combinations('ABC', 2):  # 2是组合的长度,不可省
    print(i)
('A', 'B')
('A', 'C')
('B', 'C')

4.1.4 combinations_with_replacement——元素可重复组合

import itertools

for i in itertools.combinations_with_replacement('ABC', 2):  # 2是组合的长度
    print(i)
('A', 'A')
('A', 'B')
('A', 'C')
('B', 'B')
('B', 'C')
('C', 'C')

4.2 拉链

4.2.1 zip——短拉链(Python内置)

  • zip是内置的,不需要加itertools
for i in zip("ABC", "012", "xyz"):
    print(i)
('A', '0', 'x')
('B', '1', 'y')
('C', '2', 'z')
  • 长度不一时,执行到最短的对象处,就停止
for i in zip("ABC", [0, 1, 2, 3, 4, 5]):
    print(i)
('A', 0)
('B', 1)
('C', 2)

4.2.2 zip_longest——长拉链

  • 长度不一时,执行到最长的对象处,就停止,缺省元素用 None 或 指定字符 替代
import itertools

for i in itertools.zip_longest("ABC", "012345"):
    print(i)
('A', '0')
('B', '1')
('C', '2')
(None, '3')
(None, '4')
(None, '5')
import itertools

for i in itertools.zip_longest("ABC", "012345", fillvalue = "?"):
    print(i)
('A', '0')
('B', '1')
('C', '2')
('?', '3')
('?', '4')
('?', '5')

4.3无穷迭代器

4.3.1 count(start=0, step=1)——计数

  • 创建一个迭代器,它从 start 值开始,返回均匀间隔的值
import itertools

ite = itertools.count(10)
for i in range(3):
    print(next(ite))
10
11
12

4.3.2 cycle(iterable)——循环

  • 创建一个迭代器,返回 iterable 中所有元素,无限重复
import itertools

ite = itertools.cycle("ABC")
for i in range(6):
    print(next(ite))
A
B
C
A
B
C

4.3.2 repeat(object [, times])——重复

  • 创建一个迭代器,不断重复 object 。
    除非设定参数 times ,否则将无限重复
import itertools

for i in itertools.repeat(10, 3):
    print(i)
10
10
10

4.4 chain(iterables)——锁链

  • 把一组迭代对象串联起来,形成一个更大的迭代器
import itertools

for i in itertools.chain('ABC', [1, 2, 3]):
    print(i)
A
B
C
1
2
3

4.5 enumerate(iterable, start=0)——枚举(Python内置)

  • 产出由两个元素组成的元组,结构是(index, item),其中 index 从 start 开始,item 从 iterable 中取
  • enumerate是内置的,不需要加itertools
for i in enumerate("Python", start=1):
    print(i)
(1, 'P')
(2, 'y')
(3, 't')
(4, 'h')
(5, 'o')
(6, 'n')

4.6 groupby(iterable, key=None)——分组

  • 创建一个迭代器,按照key指定的方式,返回 iterable 中连续的键和组
  • 一般来说,要预先对数据进行排序
  • key为None默认把连续重复元素分组
import itertools

for key, group in itertools.groupby('AAAABBBCCDAABBB'):
    print(key, list(group))
A ['A', 'A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
D ['D']
A ['A', 'A']
B ['B', 'B', 'B']
  • 按长度分组
import itertools

animals = ["duck", "eagle", "rat", "giraffe", "bear", "bat", "dolphin", "shark", "lion"]
animals.sort(key=len)
print(animals)

for key, group in itertools.groupby(animals, key=len):
    print(key, list(group))
['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin']
3 ['rat', 'bat']
4 ['duck', 'bear', 'lion']
5 ['eagle', 'shark']
7 ['giraffe', 'dolphin']
  • 按首字母分组
import itertools

animals = ["duck", "eagle", "rat", "giraffe", "bear", "bat", "dolphin", "shark", "lion"]
animals.sort(key=lambda x: x[0])
print(animals)

for key, group in itertools.groupby(animals, key=lambda x: x[0]):
    print(key, list(group))
['bear', 'bat', 'duck', 'dolphin', 'eagle', 'giraffe', 'lion', 'rat', 'shark']
b ['bear', 'bat']
d ['duck', 'dolphin']
e ['eagle']
g ['giraffe']
l ['lion']
r ['rat']
s ['shark']
  • itertools 其他函数可参考官方文档
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值