如何生成大小为N的字符串,由数字和大写英文字母组成,例如:

6个754z4英国U911K4型


当前回答

一种无重复的随机生成器函数,使用一个集合来存储以前生成的值。注意,如果字符串或数量非常大,这将消耗一些内存,而且可能会稍微慢一点。发电机将在给定量或达到最大可能组合时停止。

代码:

#!/usr/bin/env python

from typing import Generator
from random import SystemRandom as RND
from string import ascii_uppercase, digits


def string_generator(size: int = 1, amount: int = 1) -> Generator[str, None, None]:
    """
    Return x random strings of a fixed length.

    :param size: string length, defaults to 1
    :type size: int, optional
    :param amount: amount of random strings to generate, defaults to 1
    :type amount: int, optional
    :yield: Yield composed random string if unique
    :rtype: Generator[str, None, None]
    """
    CHARS = list(ascii_uppercase + digits)
    LIMIT = len(CHARS) ** size
    count, check, string = 0, set(), ''
    while LIMIT > count < amount:
        string = ''.join(RND().choices(CHARS, k=size))
        if string not in check:
            check.add(string)
            yield string
            count += 1


for my_count, my_string in enumerate(string_generator(6, 20)):
    print(my_count, my_string)

输出:

0 RS9N3P
1 S0GDGR
2 ZNBLFV
3 96FF97
4 38JJZ3
5 Q3214A
6 VLWNK1
7 QMT05E
8 X1ZFP0
9 MZF442
10 10L9AZ
11 GE8HIQ
12 S7PA43
13 MVLXO9
14 YX7Y0G
15 GIIKPF
16 3KCUQA
17 XHIXFV
18 BJQ5VG
19 HQF01Q

如果字符串始终需要包含字母和数字,请使用以下命令:

#!/usr/bin/env python

from typing import Generator
from random import SystemRandom as RND
from string import ascii_uppercase, digits


def string_generator(size: int = 2, amount: int = 1) -> Generator[str, None, None]:
    """
    Return x random strings of a fixed length.

    :param size: string length, defaults to 1
    :type size: int, optional
    :param amount: amount of random strings to generate, defaults to 1
    :type amount: int, optional
    :yield: Yield composed random string if unique
    :rtype: Generator[str, None, None]
    """
    if size < 2:
        print(
            'Since the string must contain letters and numbers,',
            'its size must be at least two characters',
        )
        return
    CHARS = list(ascii_uppercase + digits)
    LIMIT = len(CHARS) ** size
    count, check, string = 0, set(), ''
    while LIMIT > count < amount:
        while 1:
            string = ''.join(RND().choices(CHARS, k=size))
            if not (string.isalpha() or string.isnumeric()):
                break
        if string not in check:
            check.add(string)
            yield string
            count += 1


for my_count, my_string in enumerate(string_generator(6, 20)):
    print(my_count, my_string)

输出:

0 5JIITL
1 3W7AI1
2 8QMO10
3 ETHAI8
4 BLFPP9
5 50X2CC
6 1LI8WA
7 39CKET
8 R4IM0E
9 Q3KHGS
10 65CBIU
11 XTRHO4
12 N2XIGO
13 06VFCW
14 VE9MJ8
15 A9ADHK
16 Y5ROJ0
17 OH7EJF
18 TQ709S
19 P0DDNJ

其他回答

一个简单的例子:

import string
import random
character = string.lowercase + string.uppercase + string.digits + string.punctuation
char_len = len(character)
# you can specify your password length here
pass_len = random.randint(10,20)
password = ''
for x in range(pass_len):
    password = password + character[random.randint(0,char_len-1)]
print password

到目前为止,没有一个答案能保证存在某些类别的字符,如大写、小写、数字等;因此,其他答案可能会导致密码没有数字等。奇怪的是,这样的功能不是标准库的一部分。以下是我使用的:

def random_password(*, nchars = 7, min_nupper = 3, ndigits = 3, nspecial = 3, special=string.punctuation):
    letters = random.choices(string.ascii_lowercase, k=nchars)
    letters_upper = random.choices(string.ascii_uppercase, k=min_nupper)
    digits = random.choices(string.digits, k=ndigits)
    specials = random.choices(special, k=nspecial)

    password_chars = letters + letters_upper + digits + specials
    random.shuffle(password_chars)

    return ''.join(password_chars)

对于那些喜欢功能python的人:

from itertools import imap, starmap, islice, repeat
from functools import partial
from string import letters, digits, join
from random import choice

join_chars = partial(join, sep='')
identity = lambda o: o

def irand_seqs(symbols=join_chars((letters, digits)), length=6, join=join_chars, select=choice, breakup=islice):
    """ Generates an indefinite sequence of joined random symbols each of a specific length
    :param symbols: symbols to select,
        [defaults to string.letters + string.digits, digits 0 - 9, lower and upper case English letters.]
    :param length: the length of each sequence,
        [defaults to 6]
    :param join: method used to join selected symbol, 
        [defaults to ''.join generating a string.]
    :param select: method used to select a random element from the giving population. 
        [defaults to random.choice, which selects a single element randomly]
    :return: indefinite iterator generating random sequences of giving [:param length]
    >>> from tools import irand_seqs
    >>> strings = irand_seqs()
    >>> a = next(strings)
    >>> assert isinstance(a, (str, unicode))
    >>> assert len(a) == 6
    >>> assert next(strings) != next(strings)
    """
    return imap(join, starmap(breakup, repeat((imap(select, repeat(symbols)), None, length))))

它生成一个不定[无限]迭代器,由连接的随机序列组成,首先从给定的池中生成一个随机选择的符号的不定序列,然后将该序列分解为长度部分,然后进行连接,它应该与支持getitem的任何序列一起工作,默认情况下,它只生成一个字母数字字母的随机序列,尽管您可以轻松修改以生成其他内容:

例如生成数字的随机元组:

>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> next(irand_tuples)
(0, 5, 5, 7, 2, 8)
>>> next(irand_tuples)
(3, 2, 2, 0, 3, 1)

如果您不想使用next for generation,您可以简单地将其设置为可调用:

>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> make_rand_tuples = partial(next, irand_tuples) 
>>> make_rand_tuples()
(1, 6, 2, 8, 1, 9)

如果您想动态生成序列,只需将join设置为identity即可。

>>> irand_tuples = irand_seqs(xrange(10), join=identity)
>>> selections = next(irand_tuples)
>>> next(selections)
8
>>> list(selections)
[6, 3, 8, 2, 2]

正如其他人所提到的,如果您需要更多的安全性,请设置相应的选择功能:

>>> from random import SystemRandom
>>> rand_strs = irand_seqs(select=SystemRandom().choice)
'QsaDxQ'

默认选择器是choice,它可以为每个块多次选择相同的符号,如果相反,您希望为每个块最多选择一次相同的成员,则有一种可能的用法:

>>> from random import sample
>>> irand_samples = irand_seqs(xrange(10), length=1, join=next, select=lambda pool: sample(pool, 6))
>>> next(irand_samples)
[0, 9, 2, 3, 1, 6]

我们使用sample作为选择器,进行完整的选择,因此块的长度实际上是1,为了加入,我们只需调用next,它获取下一个完全生成的块,当然这个示例看起来有点麻烦,而且它。。。

两种方法:

import random, math

def randStr_1(字符:str,长度:int)->字符串:chars*=math.ceil(长度/长度(chars))chars=字母[0:length]chars=列表(chars)随机.洗牌(字符)返回“”.join(字符)def randStr_2(字符:str,长度:int)->字符串:返回“”.join(随机.选择(字符)用于范围(字符)中的i)基准:从timeit导入timeitsetup=“”导入操作系统,子流程,时间,字符串,随机,数学def randStr_1(字母:str,长度:int)->str:letters*=math.ceil(长度/长度(字母))letters=字母[0:长度]letters=列表(字母)随机洗牌(字母)return“”.join(字母)def randStr_2(字母:str,长度:int)->str:return“”.join(范围(长度)中i的随机选择(字母))"""打印(“方法1 vs方法2”,“,每次运行10次。”)长度为[101001000100005000010005001000000]:打印(长度,'字符:')eff1=timeit(“randStr_1(string.asci_letters,{})”.format(长度),setup=设置,数字=10)eff2=timeit(“randStr_2(string.ascii_letters,{})”.format(长度),setup=setup,number=10)打印(“\t{}s:{}s”。格式(圆形(eff1,6),圆形(eff2,6)))print('\tradio={}:{}\n'.格式(eff1/eff1,round(eff2/eff1,2)))输出:方法1与方法2,每次运行10次。100个字符:0.00141秒:0.00179秒比率=1.0:1.271000个字符:0.013857秒:0.017603秒比率=1.0:1.2710000个字符:0.13426秒:0.151169秒比率=1.0:1.1350000个字符:0.709403秒:0.855136秒比率=1.0:1.21100000个字符:1.360735秒:1.674584秒比率=1.0:1.23500000个字符:6.754923秒:7.160508秒比率=1.0:1.061000000个字符:11.232965秒:14.223914秒比率=1.0:1.27第一种方法的性能更好。

一种无重复的随机生成器函数,使用一个集合来存储以前生成的值。注意,如果字符串或数量非常大,这将消耗一些内存,而且可能会稍微慢一点。发电机将在给定量或达到最大可能组合时停止。

代码:

#!/usr/bin/env python

from typing import Generator
from random import SystemRandom as RND
from string import ascii_uppercase, digits


def string_generator(size: int = 1, amount: int = 1) -> Generator[str, None, None]:
    """
    Return x random strings of a fixed length.

    :param size: string length, defaults to 1
    :type size: int, optional
    :param amount: amount of random strings to generate, defaults to 1
    :type amount: int, optional
    :yield: Yield composed random string if unique
    :rtype: Generator[str, None, None]
    """
    CHARS = list(ascii_uppercase + digits)
    LIMIT = len(CHARS) ** size
    count, check, string = 0, set(), ''
    while LIMIT > count < amount:
        string = ''.join(RND().choices(CHARS, k=size))
        if string not in check:
            check.add(string)
            yield string
            count += 1


for my_count, my_string in enumerate(string_generator(6, 20)):
    print(my_count, my_string)

输出:

0 RS9N3P
1 S0GDGR
2 ZNBLFV
3 96FF97
4 38JJZ3
5 Q3214A
6 VLWNK1
7 QMT05E
8 X1ZFP0
9 MZF442
10 10L9AZ
11 GE8HIQ
12 S7PA43
13 MVLXO9
14 YX7Y0G
15 GIIKPF
16 3KCUQA
17 XHIXFV
18 BJQ5VG
19 HQF01Q

如果字符串始终需要包含字母和数字,请使用以下命令:

#!/usr/bin/env python

from typing import Generator
from random import SystemRandom as RND
from string import ascii_uppercase, digits


def string_generator(size: int = 2, amount: int = 1) -> Generator[str, None, None]:
    """
    Return x random strings of a fixed length.

    :param size: string length, defaults to 1
    :type size: int, optional
    :param amount: amount of random strings to generate, defaults to 1
    :type amount: int, optional
    :yield: Yield composed random string if unique
    :rtype: Generator[str, None, None]
    """
    if size < 2:
        print(
            'Since the string must contain letters and numbers,',
            'its size must be at least two characters',
        )
        return
    CHARS = list(ascii_uppercase + digits)
    LIMIT = len(CHARS) ** size
    count, check, string = 0, set(), ''
    while LIMIT > count < amount:
        while 1:
            string = ''.join(RND().choices(CHARS, k=size))
            if not (string.isalpha() or string.isnumeric()):
                break
        if string not in check:
            check.add(string)
            yield string
            count += 1


for my_count, my_string in enumerate(string_generator(6, 20)):
    print(my_count, my_string)

输出:

0 5JIITL
1 3W7AI1
2 8QMO10
3 ETHAI8
4 BLFPP9
5 50X2CC
6 1LI8WA
7 39CKET
8 R4IM0E
9 Q3KHGS
10 65CBIU
11 XTRHO4
12 N2XIGO
13 06VFCW
14 VE9MJ8
15 A9ADHK
16 Y5ROJ0
17 OH7EJF
18 TQ709S
19 P0DDNJ