Msgstr "образец больше, чем население" в random.sample python

создав простой генератор проходов для себя, я заметил, что если я хочу, чтобы мое население было только цифрами (0-9), которое в целом 10 вариантов, если я хочу, чтобы моя длина более 10, он не будет использовать какие-либо цифры больше затем один раз и вернуть ошибку "sample more than population".

Можно ли поддерживать код, но добавлять/сокращать строки кода, чтобы он работал? или я должен использовать случайный выбор использования?

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

ти

Ответ 1

Цель 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|[email protected],#/.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'

Ответ 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)

Может ли кто-нибудь подтвердить, что это более безопасно?

Ответ 3

Начиная с python_3.6 вы можете использовать random.choises(x, k=v) для ваших целей. Возвращает список элементов, выбранных из популяции с заменой. Если население пусто, поднимается IndexError.