大多数Pythonic方法从给定字符生成固定长度的随机字符串

时间:2012-01-19 00:04:28

标签: string random python

这是one of my earlier questions

的副产品

问题陈述:给定N个数字和任意(但非空)set / string / list个字符E,返回长度为N的随机字符串,由E中的字符组成。

这种做法最灵活的方式是什么?我可以选择''.join(( random.choice(E) for i in xrange(N) )),但我正在寻找一种更好的方法。 randomitertools中是否有可以执行此操作的内置函数?

奖励积分如果:

  1. 更少的函数调用
  2. 适合一行
  3. 对任何NE
  4. 的更好的普遍性
  5. 更好的运行时性能
  6. PS :这个问题实际上只是我作为一个Python鉴赏家(如果我可以自称),并试图找到优雅和艺术的编写代码的方式。我提到这个的原因是因为它看起来有点像家庭作业,我想向SO社区保证它不是。

2 个答案:

答案 0 :(得分:9)

''.join(random.sample(E*N, N))

虽然这不适用于套装,但要考虑它。 但坦率地说,

''.join(random.choice(E) for i in xrange(N))

已经很漂亮 - 它简单,清晰,富有表现力。

需要数小时思考的pythonicness并不是真正的pythonicness。

答案 1 :(得分:4)

您的解决方案看起来已经很不错了,但为了完整起见,这里有一些替代方案:

''.join(map(random.choice, [E]*N))

或者使用itertools:

from itertools import repeat
''.join(map(random.choice, repeat(E, N)))

如果您使用的是Python 2.x itertools.imap()将比map()更有效,因为它不会在内存中创建完整列表。

这是一些有趣的计时数据(在Python 2.6上测试):

>>> import timeit
>>> t1 = timeit.Timer("''.join(random.choice('abcdefghijkl') for i in xrange(3))", "import random")
>>> t2 = timeit.Timer("''.join(map(random.choice, ['abcdefghijkl']*3))", "import random")
>>> t3 = timeit.Timer("''.join(map(random.choice, repeat('abcdefghijkl', 3)))", "import random; from itertools import repeat")
>>> t4 = timeit.Timer("''.join(random.sample('abcdefghijkl'*3, 3))", "import random")
>>> t1.timeit(1000000)   # (random.choice(E) for i in xrange(N))  - OP
7.0744400024414062
>>> t2.timeit(1000000)   # map(random.choice, [E]*N)              - F.J
4.3570120334625244
>>> t3.timeit(1000000)   # map(random.choice, repeat(E, N))       - F.J
5.9411048889160156
>>> t4.timeit(1000000)   # random.sample(E*N, N)                  - DSM
6.9877378940582275

显然map(random.choice, [E]*N)是胜利者,至少对于小EN来说。