다음과 같이 임의의 30 자 문자열을 만드는 가장 간단한 방법은 무엇입니까?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
그리고 다음과 같은 16 진수 30 자리 숫자?
8c6f78ac23b4a7b8c0182d7a89e9b1
답변:
16 진수 출력을 위해 더 빠른 것을 얻었습니다. 위와 동일한 t1 및 t2 사용 :
>>> 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 임의 모듈을 한 번만 호출하고 목록을 작성하거나 읽을 필요가 없으며 나머지는 문자열 형식으로 수행합니다.
string.hexdigits. stackoverflow.com/a/15462293/311288 " string.hexdigitsreturns 0123456789abcdefABCDEF(소문자 및 대문자 모두), [...]. 대신 random.choice('0123456789abcdef')."
getrandbits대신 사용 randrange하여 더 빠르게 만듭니다.
'%030x' % random.getrandbits(60)더 빨리보다 '%030x' % random.randrange(16**30)가 큰 int 치의에서 / 어떤 변환을 할 필요가 없습니다하지 않을 가능성이 있기 때문에,
30 자리 16 진수 문자열 :
>>> import os,binascii
>>> print binascii.b2a_hex(os.urandom(15))
"c84766ca4a3ce52c3602bbf02ad1f7"
장점은 이것이 OS에서 직접 임의성을 가져오고 random ()보다 더 안전하고 빠르며 시드 할 필요가 없다는 것입니다.
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
여기보다 훨씬 빠른 솔루션 :
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447
%timeit '%030x' % randrange(16**30)While 루프 당 1.61 μs의 : 1000000 개 루프, 3의 최선을 제공 %timeit '%0x' % getrandbits(30 * 4)루프 당 396 NS : 1000000 개 루프, 3의 최선을 제공합니다
In [1]: import random
In [2]: hex(random.getrandbits(16))
Out[2]: '0x3b19'
부수적으로 이것은 timeit제안 된 두 가지 접근 방식을 사용한 결과입니다 .
사용 random.choice():
>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string")
>>> t1.timeit()
69.558588027954102
사용 binascii.b2a_hex():
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii")
>>> t2.timeit()
16.288421154022217
jcdyer가 언급 한 것에 비해 더 빠른 것이 있습니다. 이것은 그의 가장 빠른 방법의 ~ 50 %를 차지합니다.
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
base64에서 원하는 경우 :
binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]
randint (마지막 인수)에 전달 된 크기 매개 변수를 변경하여 요구 사항에 따라 출력 길이를 변경할 수 있습니다. 따라서 60 자의 경우 :
binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]
binascii.b2a_hex(np.random.rand(np.ceil(N/16)).view(dtype=int))[:N]여기서 N=30.
@eemz 솔루션보다 빠르게 수행되고 완전한 영숫자 인 믹스에 하나 이상의 답변을 추가합니다. 이것은 16 진법 답을 주지 않는다는 점에 유의하십시오 .
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"
빠른 벤치 마크 결과
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