类“ int”而不是类型“ int”:字符串索引必须为整数

时间:2019-03-21 13:18:50

标签: python python-3.x random integer

我有一个简单的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 个答案:

答案 0 :(得分:1)

您不能使用元组为列表建立索引。使用两个单独的索引操作来交换两个索引:

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() method

from secrets import SystemRandom

sysrandom = SystemRandom()

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

implementation for 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]

答案 1 :(得分:0)

这里有两个问题:

  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)