如下创建30个字符的随机字符串的最轻巧的方法是什么?
ufhy3skj5nca0d2dfh9hwd2tbk9sw1
还有一个30位的十六进制数字,如下所示?
8c6f78ac23b4a7b8c0182d7a89e9b1
Answers:
我得到了更快的十六进制输出。使用与上述相同的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.hexdigits返回0123456789abcdefABCDEF(小写和大写),[...]。而是使用random.choice('0123456789abcdef')。”
getrandbits而不是randrange使其更快。
'%030x' % random.getrandbits(60)甚至比更快'%030x' % random.randrange(16**30),可能是因为它不必进行与大整数之间的任何转换
30位十六进制字符串:
>>> 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)给出1000000循环,最好是3:每个循环1.61 µs,%timeit '%0x' % getrandbits(30 * 4)给出1000000循环,最好是3:每个循环396 ns
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(last arg)的size参数,以根据需要更改输出长度。因此,对于一个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解决方案执行速度更快且也是全字母数字的混合添加更多答案。请注意,这并没有给你一个十六进制的答案。
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