Apa cara paling ringan untuk membuat string acak yang terdiri dari 30 karakter seperti berikut?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
Dan bilangan heksadesimal 30 digit seperti berikut ini?
8c6f78ac23b4a7b8c0182d7a89e9b1
Apa cara paling ringan untuk membuat string acak yang terdiri dari 30 karakter seperti berikut?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
Dan bilangan heksadesimal 30 digit seperti berikut ini?
8c6f78ac23b4a7b8c0182d7a89e9b1
Jawaban:
Saya mendapat yang lebih cepat untuk keluaran hex. Menggunakan t1 dan t2 yang sama seperti di atas:
>>> 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 hanya membuat satu panggilan ke modul acak, tidak harus membuat atau membaca daftar, lalu melakukan sisanya dengan pemformatan string.
string.hexdigits: stackoverflow.com/a/15462293/311288 " string.hexdigitspengembalian 0123456789abcdefABCDEF(baik huruf kecil dan huruf besar), [...]. Sebagai gantinya, gunakan saja random.choice('0123456789abcdef')."
getrandbitsalih-alih randrangeuntuk membuatnya lebih cepat.
'%030x' % random.getrandbits(60)bahkan lebih cepat daripada '%030x' % random.randrange(16**30), kemungkinan karena tidak perlu melakukan konversi apa pun ke / dari orang-orang int besar
30 digit string hex:
>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"
Keuntungannya adalah ini mendapatkan keacakan langsung dari OS, yang mungkin lebih aman dan / atau lebih cepat daripada random (), dan Anda tidak perlu melakukan seeding.
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
Solusi yang secara dramatis lebih cepat daripada yang ada di sini:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
%timeit '%030x' % randrange(16**30)memberikan 1000000 loop, terbaik 3: 1,61 µs per loop sementara %timeit '%0x' % getrandbits(30 * 4)memberikan 1000000 loop, terbaik 3: 396 ns per loop
Catatan: random.choice(string.hexdigits)tidak benar, karena string.hexdigitsmengembalikan 0123456789abcdefABCDEF(baik huruf kecil dan huruf besar), jadi Anda akan mendapatkan hasil yang bias, dengan digit hex 'c' dua kali lebih mungkin muncul sebagai digit '7'. Sebagai gantinya, gunakan saja random.choice('0123456789abcdef').
Metode Lain:
from Crypto import Random
import binascii
my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
Intinya adalah: nilai byte selalu sama dengan nilai dalam hex .
In [1]: import random
In [2]: hex(random.getrandbits(16))
Out[2]: '0x3b19'
Secara kebetulan, ini adalah hasil dari penggunaan timeitdua pendekatan yang telah disarankan:
Menggunakan random.choice():
>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string")
>>> t1.timeit()
69.558588027954102
Menggunakan binascii.b2a_hex():
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t2.timeit()
16.288421154022217
Ada yang lebih cepat dibandingkan dengan apa yang telah disebutkan jcdyer. Ini membutuhkan ~ 50% dari metode tercepatnya.
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
Jika Anda ingin di base64:
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
Anda dapat mengubah parameter ukuran yang diteruskan ke randint (argumen terakhir) untuk memvariasikan panjang keluaran berdasarkan kebutuhan Anda. Jadi, untuk 60 karakter:
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]mana N=30.
menambahkan satu jawaban lagi ke campuran yang bekerja lebih cepat daripada solusi @eemz dan juga sepenuhnya alfanumerik. Perhatikan bahwa ini tidak memberi Anda jawaban heksadesimal.
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"
hasil patokan cepat
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
Ini pasti bukan versi yang paling ringan, tetapi ini acak dan mudah untuk menyesuaikan alfabet / panjang yang Anda inginkan:
import random
def generate(random_chars=12, alphabet="0123456789abcdef"):
r = random.SystemRandom()
return ''.join([r.choice(alphabet) for i in range(random_chars)])