random.choice()在同一秒内返回相同的值,如何避免这种情况?
random.choice()在同一秒内返回相同的值,如何避免这种情况?
我一直在研究如何在Python中生成随机数的类似问题。例如:类似问题 - 但我没有遇到每次返回相同值的问题。
我的随机生成器工作正常,问题在于在我认为的相同秒数调用函数时返回相同的值,这是不希望的。
我的代码如下:
def getRandomID(): token = '' letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" for i in range(1,36): token = token + random.choice(letters) return token
正如我所提到的,当在不同时刻调用该函数时,它会返回不同的值,但是当在相同时间调用函数时,它会返回相同的值。我该如何解决这个问题?
我在后端服务器中使用这个函数为前端用户生成唯一的ID,以便将其插入到数据库中,所以我无法控制发生这种情况的时间间隔。我必须使用随机令牌将用户映射到数据库,以便能够正确地将它们与数据库中的队列号插入。
在使用random.choice()函数时,有可能会出现同一秒钟内返回相同的值的情况。这是因为random.choice()函数的随机性是基于种子(seed)值生成的,而如果种子值相同,那么随机序列也会相同。解决这个问题的方法是更新种子值,以产生伪随机序列。一种选项是使用以前的结果和旧的种子进行异或运算,或者只使用结果作为新的种子值。
举个例子来说明,假设我们有以下代码:
import random def get_random_value(): seed = random.randint(1, 100) random.seed(seed) values = [1, 2, 3, 4, 5] return random.choice(values) print(get_random_value())
在这段代码中,我们使用random.randint()函数生成一个随机的种子值,并将其作为参数传递给random.seed()函数,用于设置随机数生成器的种子。然后,我们使用random.choice()函数从一个列表中随机选择一个值并返回。
然而,由于种子值是基于当前时间生成的,所以在同一秒钟内多次调用get_random_value()函数时,可能会出现相同的种子值,从而导致返回相同的随机值。
为了解决这个问题,我们可以考虑使用前一个结果与旧种子值进行异或运算的方式来更新种子值,或者直接使用结果作为新的种子值。这样,即使在同一秒钟内多次调用get_random_value()函数,由于种子值不同,我们仍然能够得到不同的随机值。
以下是更新种子值的示例代码:
import random def get_random_value(): seed = random.randint(1, 100) random.seed(seed ^ random.getrandbits(32)) values = [1, 2, 3, 4, 5] return random.choice(values) print(get_random_value())
在这个例子中,我们使用random.getrandbits(32)函数生成一个32位的随机数,并将其与旧种子值进行异或运算,得到新的种子值。然后,我们使用random.choice()函数从列表中选择一个随机值并返回。
通过更新种子值,我们能够避免在同一秒钟内多次调用random.choice()函数时返回相同的随机值。这样,我们可以获得更加随机且多样化的结果。
random.choice()返回相同的值的原因是random.seed()使用了datetime.datetime.now()作为种子,而在同一秒内多次调用该函数会得到相同的值。解决方法是将random.seed()移出函数,并在函数外部调用一次即可。
以下是整理后的文章:
在上述代码中,我们定义了一个函数getRandomID(n),用于生成n个随机id。该函数使用了random.choice()函数来从一个字符串中随机选择字符,从而生成id。然而,我们发现在同一秒内多次调用random.choice()函数时,会得到相同的结果,即返回相同的值。
这个问题的原因在于random.seed()函数使用了datetime.datetime.now()来作为随机数生成器的种子。而在同一秒内多次调用该函数,得到的种子值是相同的,从而导致random.choice()函数返回相同的结果。
为了解决这个问题,我们需要将random.seed()函数移出函数getRandomID(n),并在函数外部调用一次即可。这样,每次调用getRandomID(n)时,都会使用不同的种子值,从而保证random.choice()函数返回不同的结果。
以下是修改后的代码:
import datetime import random random.seed(datetime.datetime.now()) def getRandomID(n): letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" idList = [''.join([random.choice(letters) for j in range(1,36)]) for i in range(n)] return idList listt = getRandomID(10000000) print(len(listt)) setOfIds = set(listt) print(len(setOfIds))
通过将random.seed()函数移出getRandomID(n)函数,我们成功解决了random.choice()函数在同一秒内返回相同值的问题。现在,每次调用getRandomID(n)时,都会得到不同的随机id列表。
问题的原因是使用random.choice()
函数在同一秒内返回相同的值。这是因为在某些情况下,使用的随机数生成器的种子被设置为同一秒的时间戳,导致生成的随机数相同。
要避免这个问题,可以使用random.SystemRandom()
来改进。这个函数尝试使用os.urandom()
函数从操作系统提供的源生成随机数。下面是一个使用random.SystemRandom()
的例子:
import random sys_random = random.SystemRandom() def getRandomID(): token = '' letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" for i in range(1, 36): token = token + sys_random.choice(letters) return token print(getRandomID())
另一种避免问题的方法是使用random.choices()
函数一次返回一组选择,避免了字符串的拼接。下面是一个使用random.choices()
的例子:
import random sys_random = random.SystemRandom() def getRandomID(): letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" return ''.join(sys_random.choices(letters, k=35)) print(getRandomID())
以上两种方法都解决了问题。可以进行更大规模的测试来确认解决方案的有效性!