класс 'int' вместо типа 'int': строковые индексы должны быть целыми числами - PullRequest
0 голосов
/ 21 марта 2019

У меня есть простая функция Python, где я меняю значения в строке.Я делаю это, генерируя псевдослучайное целое число, а затем меняю его следующим индексом или предыдущим индексом, чтобы избежать исключений за пределами границ.

Однако я получаю TypeError: string indices must be integers.Когда я добавляю оператор печати для проверки типа индекса, который генерируется функцией secrets.randbelow(), он возвращает class 'int', тогда как я ожидаю type 'int'.Это то, что вызывает ошибку?

Функция

import secrets as random


def shuffle_sequence(sequence):
    sequence_len = int(len(sequence))
    for x in range(0, sequence_len):
        swap_index = random.randbelow(sequence_len)
        next_index = 0
        if swap_index != sequence_len:
            next_index = swap_index + 1
        else:
            next_index = swap_index - 1
        sequence[swap_index, next_index] = sequence[next_index, swap_index]
        x += 1
    return sequence

Я даже добавил преобразование типа int в первую строку функции, надеясь, что это поможет, но она возвращаеттот же класс int, что и ожидается.

Для пояснения, sequence - это строка букв, цифр и символов.

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Вы не можете использовать кортеж для индексации списка. Используйте две отдельные операции индексирования для замены двух индексов:

sequence[swap_index], sequence[next_index] = sequence[next_index], sequence[swap_index]

Обратите внимание, что ваш тест swap_index != sequence_len никогда не будет верным, поскольку secrets.randbelow() уже гарантирует, что вы получите значение от 0 до ниже значения аргумента. Вы столкнетесь с ошибкой индекса, когда swap_index равен sequence_len - 1, потому что тогда next_index устанавливается равным sequence_len, что не является допустимым индексом.

Далее, если sequence является неизменяемым типом, например строкой, то присвоение индексам не может работать. Сначала вам нужно будет преобразовать строку в изменяемую последовательность, например, список, затем преобразовать обратно в строку (используя str.join()).

И, наконец, ваша реализация меняет местами только последовательные элементы, что не совсем правильно. Вы должны рассмотреть все элементы, которые еще не поменялись местами.

И, наконец, чтобы «перетасовать» последовательность «безопасно», просто используйте класс secrets.SystemRandom() и назовите его shuffle() метод :

from secrets import SystemRandom

sysrandom = SystemRandom()

def shuffle_sequence(sequence):
    sequence = list(sequence)
    sysrandom.shuffle(sequence)
    return ''.join(sequence)

Реализация для Random.shuffle() перебирает индексы последовательности в обратном порядке и выбирает случайный элемент, который находится перед индексом итерации:

for next_index in reversed(range(1, sequence_len)):
    swap_index = random.randbelow(next_index)
    sequence[swap_index], sequence[next_index] = sequence[next_index], sequence[swap_index]
0 голосов
/ 21 марта 2019

Здесь есть две проблемы:

  1. Вы пытаетесь проиндексировать строку с помощью кортежа, а не целого числа.
  2. Строки являются неизменяемыми, поэтому вы не можете поменять местами двесимволы в существующей строке.

Вам необходимо развернуть строку в список, выполнить там обмен, а затем соединить элементы списка обратно в строку.

def shuffle_sequence(sequence):
    # "abc" -> ["a", "b", "c"]
    elements = list(sequence)

    sequence_len = int(len(sequence))
    for x in range(0, sequence_len):
        swap_index = random.randbelow(sequence_len)
        next_index = 0
        if swap_index != sequence_len:
            next_index = swap_index + 1
        else:
            next_index = swap_index - 1

        # Swap elements of the list
        elements[swap_index], elements[next_index] = elements[next_index], elements[swap_index]
        x += 1

    # Combine the elements into a single string
    return ''.join(elements)
...