Искам да генерирам низ с размер N.
Той трябва да се състои от цифри и главни английски букви, като например:
Как мога да постигна това по питоничен начин?
Отговор на един ред:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
или още по-кратко, като се започне от Python 3.6, като се използва random.choices()
:
''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
Криптографски по-сигурна версия; вижте https://stackoverflow.com/a/23728630/2213647:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Подробно, с чиста функция за по-нататъшно повторно използване:
>>> import string
>>> import random
>>> def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
... return ''.join(random.choice(chars) for _ in range(size))
...
>>> id_generator()
'G5G74W'
>>> id_generator(3, "6793YUIO")
'Y3U'
Как работи това?
Импортираме string
, модул, който съдържа последователности от общи ASCII символи, и random
, модул, който се занимава с генериране на случайни числа.
string.ascii_uppercase + string.digits
просто обединява списък от символи, представляващи главни ASCII символи и цифри:
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
След това използваме разбиране на списък, за да създадем списък от 'n' елементи:
>>> range(4) # range create a list of 'n' numbers
[0, 1, 2, 3]
>>> ['elem' for _ in range(4)] # we use range to create 4 times 'elem'
['elem', 'elem', 'elem', 'elem']
В горния пример използваме [
за създаване на списъка, но не го правим във функцията id_generator
, така че Python не създава списъка в паметта, а генерира елементите в движение, един по един (повече за това тук).
Вместо да поискаме да се създаде 'n' пъти низът elem
, ще поискаме от Python да създаде 'n' пъти случаен символ, избран от поредица от символи:
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
Следователно random.choice(chars) for _ in range(size)
наистина създава поредица от символи с размер size
. Символи, които се избират на случаен принцип от chars
:
>>> [random.choice('abcde') for _ in range(3)]
['a', 'b', 'b']
>>> [random.choice('abcde') for _ in range(3)]
['e', 'b', 'e']
>>> [random.choice('abcde') for _ in range(3)]
['d', 'a', 'c']
След това просто ги съединяваме с празен низ, така че последователността се превръща в низ:
>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
По-прост, по-бърз, но малко по-неслучаен начин е да използвате random.sample
вместо да избирате всяка буква поотделно, Ако са разрешени n повторения, увеличете случайната база n пъти, напр.
import random
import string
char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))
Забележка: random.sample предотвратява повторното използване на символите, умножаването на размера на набора от символи прави възможни многократните повторения, но те все още са по-малко вероятни, отколкото при чист случаен избор. Ако изберем низ с дължина 6 и изберем 'X' като първи символ, в примера за избор вероятността да получим 'X' за втори символ е същата като вероятността да получим 'X' като първи символ. При реализацията на random.sample вероятността да получите 'X' като всеки следващ символ е само 6/7 от вероятността да го получите като първи символ
Мислех, че никой не е отговорил на това все още lol! Но ето, че и аз се опитах да го направя:
import random
def random_alphanumeric(limit):
#ascii alphabet of all alphanumerals
r = (range(48, 58) + range(65, 91) + range(97, 123))
random.shuffle(r)
return reduce(lambda i, s: i + chr(s), r[:random.randint(0, len(r))], "")