Подтвердить что ты не робот

Почему некоторый код детерминирован в Python2 и не является детерминированным в Python 3?

Я пытаюсь написать script для вычисления всех возможных совпадений совпадений с нечеткой строкой для короткой строки или "kmer" и того же кода, который работает в Python 2.7.X дает мне не- детерминированный ответ с Python 3.3.X, и я не могу понять, почему.

Я перебираю словарь, itertools.product и itertools.combinations в моем коде, но я перебираю все их до завершения без перерывов или продолжается. Кроме того, я сохраняю все свои результаты в отдельном словаре, а не в том, что я повторяю. Короче говоря, я не делаю никаких ошибок, которые очевидны для меня, так почему поведение отличается от Python2 и Python3?

Пример, немного упрощенный код ниже:

import itertools

def find_best_fuzzy_kmer( kmers ):
    for kmer, value in kmers.items():
        for similar_kmer in permute_string( kmer, m ):
            # Tabulate Kmer

def permute_string( query, m ):
    query_list = list(query)
    output = set() # hold output
    for i in range(m+1):
        # pre-calculate the possible combinations of new bases
        base_combinations = list(itertools.product('AGCT', repeat=i))
        # for each combination `idx` in idxs, replace str[idx]
        for positions in itertools.combinations(range(len(query_list)), i):
            for bases in base_combinations:
                # Generate Permutations and add to output
    return output
4b9b3361

Ответ 1

Если на "недетерминированный" означает порядок, в котором появляются словарные ключи (когда вы перебираете словарь), изменяется от run to run, а словарные клавиши - строки, скажите так, Тогда я могу помочь. Но пока вы ничего не сказали об этом: -)

Предполагая, что проблема, здесь небольшая программа:

d = dict((L, i) for i, L in enumerate('abcd'))
print(d)

а вывод из 4 работает под Python 3.3.2:

{'d': 3, 'a': 0, 'c': 2, 'b': 1}
{'d': 3, 'b': 1, 'c': 2, 'a': 0}
{'d': 3, 'a': 0, 'b': 1, 'c': 2}
{'a': 0, 'b': 1, 'c': 2, 'd': 3}

В этой части вывода python -h вызывается причина:

Other environment variables:
...
PYTHONHASHSEED: if this variable is set to 'random', a random value is used
   to seed the hashes of str, bytes and datetime objects.  It can also be
   set to an integer in the range [0,4294967295] to get hash values with a
   predictable seed.

Это полузащищенное "исправление безопасности", предназначенное для предотвращения атак DOS, основанных на построении входных данных dict, которые спровоцировали поведение в квадратичном режиме. "random" является значением по умолчанию в Python3.

Вы можете отключить это, установив envar PYTHONHASHSEED в целое (ваш выбор - выберите 0, если вам все равно). Затем итерация dict со строковыми клавишами будет производить их в том же порядке в течение пробегов.

Как @AlcariTheMad сказал в комментарии, вы можете включить поведение Python3 по умолчанию в Python 2 через python -R ....