Wie (warum?) Wurde keine der (gut ausgearbeiteten) Antworten akzeptiert?
R2evans
Antworten:
119
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.1650378704071049.02927398681640625.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.
Nett. Generieren Sie einfach eine 30 hexadezimale Zufallszahl und drucken Sie sie aus. Offensichtlich, wenn darauf hingewiesen wird. Schön.
Eemz
Interessanterweise habe ich irgendwie vergessen, dass Python (und das Zufallsmodul) Bigints nativ handhabt.
Wump
3
Siehe yaronfs Antwort unten zur Verwendung von 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')."
Thomas
2
Verwenden Sie getrandbitsstatt randrange, um es noch schneller zu machen.
Robinst
@robinst hat einen guten Punkt. '%030x' % random.getrandbits(60)ist sogar schneller als '%030x' % random.randrange(16**30), wahrscheinlich, weil es keine Konvertierung zu / von Big-Ints machen muss
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.
Das ist interessant und wahrscheinlich eine gute Wahl, um die gewünschte 30-stellige Hex-Zahl zu generieren. könnte wahrscheinlich urandom und einen Slice-Operator verwenden, um auch die alphanumerische Zeichenfolge zu generieren.
Eemz
Ich habe mir die anderen Funktionen in binascii angesehen, sie haben base64 und uuencode, aber keine Möglichkeit, die erste Art von Strings zu generieren, die er will (base36).
Wump
1
Ist dies zufällig / eindeutig genug, um beispielsweise in Sitzungstoken verwendet zu werden?
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
Ein Benutzer muss alle Methoden auf demselben Computer ausprobieren, um eine genaue Basislinie zu erhalten. Hardwarespezifikationen können einen großen Unterschied machen. >>>> timeit.timeit ("'% 0x'% getrandbits (30 * 4)", "vom zufälligen Import getrandbits") 0.2471246949999113 </ pre>
ptay
Vielen Dank, dies viel schneller als die anderen oben. %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
frmdstryr
15
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').
Es gibt eine schnellere im Vergleich zu dem, was jcdyer erwähnt hat. Dies dauert ~ 50% seiner schnellsten Methode.
from numpy.random.mtrand importRandomStateimport 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.62.253110885620117<-- this on python 2.7.5
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:
Zu Ihrer Information: Diese Antwort wurde als minderwertig gekennzeichnet. Vielleicht möchten Sie sie verbessern.
Oguz Ismail
Verbesserungsvorschläge?
Bob
Keine Ahnung. Ich dachte nur, du solltest das wissen
oguz ismail
0
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 =10print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))# random_choice_algo 8.180561417000717print("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)])
Antworten:
Ich habe eine schnellere für die Hex-Ausgabe. Verwenden Sie die gleichen t1 und t2 wie oben:
t3
führt nur einen Aufruf des Zufallsmoduls durch, muss keine Liste erstellen oder lesen und erledigt den Rest mit der Formatierung von Zeichenfolgen.quelle
string.hexdigits
: stackoverflow.com/a/15462293/311288 "string.hexdigits
gibt0123456789abcdefABCDEF
(sowohl Klein- als auch Großbuchstaben) zurück, [...]. Verwenden Sie stattdessen einfachrandom.choice('0123456789abcdef')
."getrandbits
stattrandrange
, 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 muss30-stellige Hex-Zeichenfolge:
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.
quelle
In Py3.6 + können Sie auch das neue Standardmodul verwenden
secrets
:quelle
quelle
random.SystemRandom().choice
Dramatisch schnellere Lösung als hier:
quelle
%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 SchleifeHinweis:
random.choice(string.hexdigits)
ist falsch, dastring.hexdigits
zurückgegeben wird0123456789abcdefABCDEF
(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 einfachrandom.choice('0123456789abcdef')
.quelle
Eine andere Methode :
Der Punkt ist: Der Bytewert ist immer gleich dem Wert in hex .
quelle
einzeilige Funktion:
quelle
Dies ist übrigens das Ergebnis der Verwendung
timeit
der beiden vorgeschlagenen Ansätze:Verwenden von
random.choice()
:Verwenden von
binascii.b2a_hex()
:quelle
Es gibt eine schnellere im Vergleich zu dem, was jcdyer erwähnt hat. Dies dauert ~ 50% seiner schnellsten Methode.
Wenn Sie in base64 wollen:
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:
quelle
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]
woN=30
.quelle
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.
eine schnelle Benchmark-Rendite
quelle
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:
quelle