当前位置:   article > 正文

Python中生成随机数据random模块总结_random.randbytes

random.randbytes

1. 伪随机

查看 python 标准库random的文档, 第一行是 

该模块为各种分布实现了伪随机数生成器

 random模块本质上是用数据的算法来实现的, 生成的数据看似随机, 但依然是可重现的。

1.1 seed, getstate, setstate 

通过指定初始化随机数, random.seed 可以使后续生成的随机数具有确定性.

  1. In [1]: import random
  2. In [2]: random.seed(100)
  3. In [3]: [random.random() for _ in range(3)]
  4. Out[3]: [0.1456692551041303, 0.45492700451402135, 0.7707838056590222]
  5. In [4]: random.seed(100)
  6. In [5]: [random.random() for _ in range(3)]
  7. Out[5]: [0.1456692551041303, 0.45492700451402135, 0.7707838056590222]

 从以上代码可以看到, 在 In [4] 这行代码将seed重置为100后, 后续再次调用random.random()时, 和第一次产生的数据是完全相同的

除了指定seed, random模块还提供了2个方法 getstate(), setstate() 来捕获和恢复生成器当前内部状态的对象. 

  1. In [6]: st = random.getstate()
  2. In [7]: [random.random() for _ in range(3)]
  3. Out[7]: [0.705513226934028, 0.7319589730332557, 0.43351443489540376]
  4. In [8]: random.setstate(st)
  5. In [9]: [random.random() for _ in range(3)]
  6. Out[9]: [0.705513226934028, 0.7319589730332557, 0.43351443489540376]

2. random中的常用方法

2.1 随机字节 randbytes

randbytes接收1个参数, 用于返回指定长度的随机字节数据

  1. In [10]: random.randbytes(2)
  2. Out[10]: b'\x80d'
  3. In [11]: random.randbytes(4)
  4. Out[11]: b'\xc7np\xfc'

2.2 随机整数  randint, randrange, getrandbits

randint(start, end) 接受 2 个参数 返回闭区间 start,  end 中的一个数.

  1. In [1]: import random
  2. In [2]: {random.randint(1, 10) for _ in range(100)}
  3. Out[2]: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

随机取值100次, 将结果转换为一个集合, 可以看到, 数据范围为 [1, 10] 

randrange(start, end, step) , 等效于choice(range(start, stop, step)), 从指定起止坐标和步长的列表中随机取一个数据, 数据区间左开右比 start, end )

  1. # randrange 返回右开区间的数据
  2. In [3]: {random.randrange(1, 10) for _ in range(100)}
  3. Out[3]: {1, 2, 3, 4, 5, 6, 7, 8, 9}
  4. # randrange 可以省略start的值, 默认使用0
  5. In [4]: {random.randrange(10) for _ in range(100)}
  6. Out[4]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
  7. # randrange 指定步长
  8. In [5]: {random.randrange(1, 10, step=3) for _ in range(100)}
  9. Out[5]: {1, 4, 7}

getrandbits(k), 返回一个2进制k位能表达的数据大小中的随机一个数据. 数据范围 [ 0, 2^k ]

  1. # getrandbits 返回0-2^4之间的数据
  2. In [6]: {random.getrandbits(4) for _ in range(100)}
  3. Out[6]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}

2.3 随机序列 choice, choices, shuffle, sample

choice(seq), 从非空序列seq中随机返回一个值

  1. In [7]: data = ['A', 'B', 'C', 'D', 'E', 'F']
  2. In [8]: random.choice(data)
  3. Out[8]: 'D'
  4. In [9]: random.choice(data)
  5. Out[9]: 'E'

sample(seq, k), 从非空序列seq中随机取k个元素, 返回一个列表, 数据不可以重复.

  1. In [10]: random.sample(data, 2)
  2. Out[10]: ['E', 'B']
  3. In [11]: random.sample(data, 4)
  4. Out[11]: ['D', 'E', 'A', 'F']

shuffle(seq), 将seq数据原地打乱顺序

  1. In [12]: data = ['A', 'B', 'C', 'D', 'E', 'F']
  2. In [13]: random.shuffle(data)
  3. In [14]: data
  4. Out[14]: ['F', 'D', 'C', 'A', 'B', 'E']

choices(seq, weights=None , * , cum_weights=None , k=1), 从非空序列seq中随机取k个元素, 返回一个列表, 数据可以重复, weightscum_weights字段为对应位置数据的权重和相对权重, 如果指定权重, 权重列表需要和seq长度一致.

  1. In [15]: data = ['A', 'B', 'C', 'D', 'E', 'F']
  2. In [16]: random.sample(data, k=8)
  3. ---------------------------------------------------------------------------
  4. ValueError: Sample larger than population or is negative
  5. In [17]: random.choices(data, k=8)
  6. Out[17]: ['E', 'A', 'D', 'F', 'F', 'E', 'A', 'C']

从以上代码可以看到, choices与sample的最大不同是, choices获取的数据可以重复, 这样可以生成长度比原数据还要大的列表. 

下面为了便于理解choices函数中的权重参数的使用, 需要使用collections.Counter来更直观的统计随机取的数据的个数.

  1. In [18]: Counter(random.choices(data, k=600))
  2. Out[18]: Counter({'F': 114, 'A': 97, 'C': 103, 'B': 92, 'E': 105, 'D': 89})

可以看到, 默认所有数据权重一致, 所以choices取600个数据, ABCDEF每个数据大概是100次左右.

下面我们指定权重weights字段

  1. In [19]: Counter(random.choices(data, weights=[0, 0, 10, 10, 20, 20], k=600))
  2. Out[19]: Counter({'E': 189, 'F': 209, 'C': 104, 'D': 98})

可以看到, 指定了weithts =[0, 0, 10, 10, 20, 20]之后, 字符AB因为对应的权重为0, 所以结果中1次都没有出现, 字符C D E F 按照配的权重按照 1 : 1 : 2 : 2的比例出现

还可以使用 cum_weights 参数。它代表交换权重。cum_weights与weights的换算关系为 

cum_weights[0] = weights[0]

cum_weights[n] = sum(weights[:n-1])

如  weights = [5,10,20,30,35] 对应的

cum_weights = [5,15,35,65,100]

  1. In [20]: Counter(random.choices(data, cum_weights=[0, 0, 10, 20, 40, 60], k=600))
  2. Out[20]: Counter({'C': 101, 'F': 204, 'E': 198, 'D': 97})

将cum_weights=[0, 0, 10, 20, 40, 60] 可以达到和之前使用weithts =[0, 0, 10, 10, 20, 20], 相同的效果.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/834112
推荐阅读
相关标签