Я пытаюсь сгенерировать уникальный идентификатор числа для некоторых модульных тестов, и я увидел где-то предложение использовать что-то вроде:

def unique_id():
    time.sleep(0.000001) # smallest precision for time.time()
    return time.time()

Мне интересно, если вызов hash () всегда будет по крайней мере 0,000001, поэтому я мог бы использовать:

def unique_id():
    return hash(time.time())

Может ли это когда-либо возвращать одно и то же значение дважды, если я вызываю его последовательно в однопоточном приложении?

Редактировать: жирным шрифтом слово «ЦИФРЫ», потому что каждый человек упустил его.

2
Gerald Thibault 18 Дек 2015 в 00:46

3 ответа

Лучший ответ

Это тривиально, чтобы ответить из приглашения Python:

>>> import time; print hash(time.time()) == hash(time.time())
True

(Если вы видите False, вам просто повезло.)

Так да. Современные компьютеры достаточно быстры, чтобы хэшировать их менее чем за 0,000001 секунды. Фактически, когда я написал это как цикл while, который увеличил счетчик, оказалось, что на моей машине Python может получить время и хешировать его более 5000 раз подряд, не видя разницы. Не удивительно: хеш используется для размещения объектов в хеш-таблице (словаре), поэтому одним из его основных требований является скорость.

В любом случае, нет требования или гарантии, что hash() возвращает уникальный идентификатор для каждого объекта. Два различных значения time.time() (или любого типа) могут иметь одинаковый хеш, и ничто не мешает этим двум значениям быть «смежными» по определению.

То, что вы хотите, как указали другие, это UUID. Не изобретай велосипед. Если вы не можете использовать UUID, используйте что-то, что никогда не сможет дублироваться, например, счетчик.

1
kindall 17 Дек 2015 в 22:11

Эван Фосмарк уже накрыл это.

Но я хочу добавить, что "хэш" -функция Python, насколько я могу судить, является 32-битной или 64-битной. Я даже не знаю, как это реализовано, но я сомневаюсь, что это криптографически случайно. Ожидаются коллизии из-за некачественной хэш-функции.

1
Dragontamer5788 17 Дек 2015 в 22:05

Если вам нужно уникальное значение, рекомендуется использовать uuid библиотека. Пример:

>>> import uuid
>>> uuid.uuid4()
UUID('514c2bd7-75a3-4541-9075-d66560f42b5c')
>>> str(uuid.uuid4())
'6faad714-c2df-448b-b072-f91deb380e84'

Если вам нужны только числовые значения, используйте random библиотеку.

>>> import random
>>> INT_MAX = sys.maxint #  Set INT_MAX to the max value for your given INT column
>>> random.randint(0, INT_MAX)
5188925271790705047
6
Evan Fosmark 17 Дек 2015 в 22:25