Was ist die einfachste Methode, um eine zufällige Zeichenfolge mit 30 Zeichen wie die folgende zu erstellen?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
Und eine hexadezimale Zahl von 30 Stellen wie die folgende?
8c6f78ac23b4a7b8c0182d7a89e9b1
Was ist die einfachste Methode, um eine zufällige Zeichenfolge mit 30 Zeichen wie die folgende zu erstellen?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
Und eine hexadezimale Zahl von 30 Stellen wie die folgende?
8c6f78ac23b4a7b8c0182d7a89e9b1
Antworten:
Ich habe eine schnellere für die Hex-Ausgabe. Verwenden Sie die gleichen t1 und t2 wie oben:
>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random")
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random")
>>> for t in t1, t2, t3:
... t.timeit()
...
28.165037870407104
9.0292739868164062
5.2836320400238037
t3 führt nur einen Aufruf des Zufallsmoduls durch, muss keine Liste erstellen oder lesen und erledigt den Rest mit der Formatierung von Zeichenfolgen.
string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitsgibt 0123456789abcdefABCDEF(sowohl Klein- als auch Großbuchstaben) zurück, [...]. Verwenden Sie stattdessen einfach random.choice('0123456789abcdef')."
getrandbitsstatt randrange, um es noch schneller zu machen.
'%030x' % random.getrandbits(60)ist sogar schneller als '%030x' % random.randrange(16**30), wahrscheinlich, weil es keine Konvertierung zu / von Big-Ints machen muss
30-stellige Hex-Zeichenfolge:
>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"
Der Vorteil ist, dass dies die Zufälligkeit direkt vom Betriebssystem erhält, was sicherer und / oder schneller als das random () sein kann und Sie es nicht festlegen müssen.
In Py3.6 + können Sie auch das neue Standardmodul verwenden secrets:
>>> import secrets
>>> secrets.token_hex(15)
'8d9bad5b43259c6ee27d9aadc7b832'
>>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable
'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
str = "".join(lst)
print str
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
random.SystemRandom().choice
Dramatisch schnellere Lösung als hier:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
%timeit '%030x' % randrange(16**30)gibt 1000000 Schleifen, am besten 3: 1,61 µs pro Schleife, während %timeit '%0x' % getrandbits(30 * 4)1000000 Schleifen, am besten 3: 396 ns pro Schleife
Hinweis: random.choice(string.hexdigits)ist falsch, da string.hexdigitszurückgegeben wird 0123456789abcdefABCDEF(sowohl in Klein- als auch in Großbuchstaben), sodass Sie ein voreingenommenes Ergebnis erhalten, bei dem die hexadezimale Ziffer 'c' doppelt so häufig erscheint wie die Ziffer '7'. Verwenden Sie stattdessen einfach random.choice('0123456789abcdef').
Dies ist übrigens das Ergebnis der Verwendung timeitder beiden vorgeschlagenen Ansätze:
Verwenden von random.choice():
>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string")
>>> t1.timeit()
69.558588027954102
Verwenden von binascii.b2a_hex():
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t2.timeit()
16.288421154022217
Es gibt eine schnellere im Vergleich zu dem, was jcdyer erwähnt hat. Dies dauert ~ 50% seiner schnellsten Methode.
from numpy.random.mtrand import RandomState
import binascii
rand = RandomState()
lo = 1000000000000000
hi = 999999999999999999
binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30]
>>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \
... 'from __main__ import lo,hi,rand,binascii').timeit()
1.648831844329834 <-- this is on python 2.6.6
2.253110885620117 <-- this on python 2.7.5
Wenn Sie in base64 wollen:
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
Sie können den an randint (last arg) übergebenen Größenparameter ändern, um die Ausgabelänge je nach Ihren Anforderungen zu variieren. Also, für einen 60 Zeichen:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]wo N=30.
In [1]: import random
In [2]: hex(random.getrandbits(16))
Out[2]: '0x3b19'
Hinzufügen einer weiteren Antwort zu der Mischung, die schneller als die @ ememz-Lösung ist und außerdem vollständig alphanumerisch ist. Beachten Sie, dass dies nicht nicht geben Sie eine hexadezimale Antwort.
import random
import string
LETTERS_AND_DIGITS = string.ascii_letters + string.digits
def random_choice_algo(width):
return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))
def random_choices_algo(width):
return ''.join(random.choices(LETTERS_AND_DIGITS, k=width))
print(generate_random_string(10))
# prints "48uTwINW1D"
eine schnelle Benchmark-Rendite
from timeit import timeit
from functools import partial
arg_width = 10
print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))
# random_choice_algo 8.180561417000717
print("random_choices_algo", timeit(partial(random_choices_algo, arg_width)))
# random_choices_algo 3.172438014007639
Dies ist sicherlich nicht die leichteste Version, aber es ist zufällig und es ist einfach, das gewünschte Alphabet / die gewünschte Länge anzupassen:
import random
def generate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return ''.join([r.choice(alphabet) for i in range(random_chars)])