【问题标题】:class 'int' instead of type 'int': string indices must be integers类“int”而不是类型“int”:字符串索引必须是整数
【发布时间】:2019-08-12 08:41:58
【问题描述】:

我有一个简单的 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 是一串字母、数字和符号。

【问题讨论】:

  • Python 2 将其称为type,Python 3 将其统一为class。你永远不会在 Python 3 中看到 <type 'int'>
  • 您正在尝试使用元组索引sequence
  • 另外,字符串是不可变的;您不能分配给现有字符串中的特定位置。

标签: python python-3.x random integer


【解决方案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]

【讨论】:

  • 我是 Python 新手,一直在研究事物的工作原理,已经离开开发世界一段时间了。感谢您的耐心等待。
【解决方案2】:

这里有两个问题:

  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)

【讨论】:

  • 这仍然有一个非零的机会抛出一个IndexError,它只交换连续的元素
  • 是的,我什至没有尝试解决算法中的任何错误,只是明显的机械错误。
猜你喜欢
  • 2013-09-04
  • 1970-01-01
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多