random.sample python中的“大于人口的样本”

时间:2013-12-31 18:03:37

标签: python string random

为自己创建一个简单的传递生成器,我注意到如果我希望我的人口只是数字(0-9),这是10个选项,如果我想要我的长度超过10,它不会使用任何数字更多然后一次返回"样本大于人口"错误。

是否可以维护代码,但添加/减少代码行以便它可以工作?或者我是否有使用随机选择?

import string
import random

z=int(raw_input("for: \n numbers only choose 1, \n letters only choose 2, \n letters and numbers choose 3, \n for everything choose 4:"))

if z==1:
    x=string.digits
elif z==2:
    x=string.letters
elif z==3:
    x=string.letters+string.digits
elif z==4:
    x=string.letters+string.digits+string.punctuation
else:
    print "die in a fire"

y=int(raw_input("How many passwords would you like?:"))
v=int(raw_input("How long would you like the password to be?:"))

for i in range(y):
    string=""
    for n in random.sample(x,v):
        string+=n
    print string

TY

3 个答案:

答案 0 :(得分:12)

random.sample()目的是随机选择输入序列的子集,而不会多次挑选任何一个元素。如果您的输入序列没有重复,那么您的输出也不会。

正在寻找一个子集;你想要从输入序列中单个随机选择,重复多次。元素可以使用多次。在循环中使用random.choice()

for i in range(y):
    string = ''.join([random.choice(x) for _ in range(v)])
    print string

这会创建一个长度为v的字符串,其中来自x的字符可以多次使用。

快速演示:

>>> import string
>>> import random
>>> x = string.letters + string.digits + string.punctuation
>>> v = 20
>>> ''.join([random.choice(x) for _ in range(v)])
'Ms>V\\0Mf|W@R,#/.P~Rv'
>>> ''.join([random.choice(x) for _ in range(v)])
'TsPnvN&qlm#mBj-!~}3W'
>>> ''.join([random.choice(x) for _ in range(v)])
'{:dfE;VhR:=_~O*,QG<f'

答案 1 :(得分:2)

@Martijn Pieters是对的。 但是因为他们在https://docs.python.org/3.4/library/random.html陈述:

  

警告:此模块的伪随机生成器不应用于安全目的。如果需要加密安全的伪随机数生成器,请使用os.urandom()或SystemRandom。

这个用于生成密码的目的,我建议这种方法:

import string
import random

set = string.letters + string.digits + string.punctuation
length = 20

password = ''.join( [ random.SystemRandom().choice( set) for _ in range( length) ] )

print( password)

有人可以确认这更安全吗?

答案 2 :(得分:0)

自python_3.6起,您可以使用random.choises(x, k=v)来实现您的目的。它返回一个k大小的元素列表,该列表从总体中选择并替换。如果填充为空,则引发IndexError。