Случайное начальное число для порядка элементов в преобразовании Python в список преобразования - PullRequest
0 голосов
/ 25 февраля 2020

Я выполнял некоторый код в записной книжке Jupyter и заметил, что каждый раз, когда я его запускал, вывод был разным, несмотря на то, что в моей программе явно не было случайности.

Я сузил его до строки, которая удаляет все повторяющиеся элементы из списка.

l = list(set(l))

Я заметил две вещи:

  • Если я повторно запустить тот же код в том же ядре Jupyter, я всегда получаю один и тот же вывод для l, но

  • Если я открываю другую записную книжку, я получаю другой вывод.

Существует ли какой-то скрытый случайный начальный номер, который используется для преобразования set -> list для данного ядра? Как это работает под капотом, и что бы я сделал, если бы я хотел получить детерминированный c вывод из приведенного выше кода?

1 Ответ

1 голос
/ 25 февраля 2020

A set функционирует почти так же, как dict, с hash вашего объекта в качестве ключа. По умолчанию функция __hash__ большинства объектов (в CPython) основана на их id, что, в свою очередь, зависит от их адреса в памяти.

Новое ядро ​​означает, что объекты имеют другой адрес, что означает другой id, другой hash и другой порядок итератора, который дает набор.

Это реализация -зависимый, так что вы не можете полагаться на это, все, что я могу сказать, это CPython, до сих пор работает таким образом. На что вы можете положиться - это set, который (бесполезно) не упорядочен.

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

def could_add(s, x):
    if x in s:
        return False
    else:
        s.add(x)
        return True

seen = set()
[x for x in l if could_add(seen, x)]

(Хотя я полностью согласен с комментарием Бармара - если порядок имеет значение, они должны сортироваться.)

...