【问题标题】:Python: Altering a specific position in a stringPython:改变字符串中的特定位置
【发布时间】:2018-08-16 07:01:03
【问题描述】:

这是我的第一篇文章,感谢您的帮助。

我正在解决 Python 中的一个问题,我需要创建一个hangman 程序,但我遇到了一个问题,我有点卡住了。我已经制定了我想要做的框架,但我被语法困住了。

本质上,我正在编写一个函数,给定一个单词和一个字母列表,我必须返回一个字符串,该字符串显示哪些字母是正确的猜测以及单词中的哪些位置仍然是空白的。例如,如果秘密单词是'apple',并且猜测的字母列表是['e', 'i', 'k', 'p', 'r', 's'],那么函数应该返回'_ pp_ e'。

我解决这个问题的方法是为秘密单词创建一个变量,并遍历每个字母以检查它是否在猜测的字母列表中。如果它在列表中,则该字母将保留;如果不是,它将被替换为“_”。迭代结束后,函数将返回secretWord变量。

到目前为止,这是我的代码:

def getGuessedWord(secretWord, lettersGuessed):
    '''
    secretWord: string, the word the user is guessing
    lettersGuessed: list, what letters have been guessed so far
    returns: string, comprised of letters and underscores that represents
      what letters in secretWord have been guessed so far.
    '''
    for i in secretWord:
        if i not in lettersGuessed:
            secretWord[len(i)] == '_ '
    return secretWord

我的问题在于函数的第三行 (secretWord[len(i)] == '_')。我不知道如何让 Python 用“_”替换我想要的字母。由于'i'是一个字符,而不是一个整数,我不能说secretWord[i] = '_'。我承认我有点初学者,操作字符串对我来说仍然很困难,所以对于有更多经验的人来说,这可能是一个非常容易解决的问题。

再次感谢您的帮助!

【问题讨论】:

    标签: string python-3.x iteration


    【解决方案1】:

    你想做什么

    首先,您很苦恼,因为您不知道如何引用要替换的字母的索引。当您执行for i in secretWord 时,您确实没有得到保存索引的变量;在您的代码中,您的 i 变量包含字母本身。 Python 提供了一个方便的函数,用于您想要循环某个集合但又想在循环时跟踪索引的情况:

    for i, letter in enumerate(secretWord):
        if letter not in lettersGuessed:
            # WATCH OUT: == is for comparison (is this equal to that?)
            #            = is for assignment (make this equal to that)
            secretWord[i] = '_ '
    

    enumerate 生成(索引、内容)元组列表,您将其分解为 iletter 变量。

    现在这就是您要编写的代码。呵呵……

    ...不行。

    解决方案

    这是因为 Python 中的字符串是不可变的——一旦创建,就无法更改。这可能看起来非常令人生畏,但是您制作了修改后的字符串副本并将它们分配给不同的变量(甚至是最初保存不同字符串的同一个变量)。你可能一直在做这件事而没有意识到。但是你绝对不能做的是直接为现有字符串的一部分分配不同的东西。

    @DannyMoshe 指出了解决此问题的方法。 replace 方法为您提供调用它的字符串的副本,并对其执行查找和替换。现在您可以将此副本分配给您的原始secretWord 变量:secretWord = secretWord.replace(letter, '_ ')。您的原始字符串被丢弃,您的 secretWord 变量现在引用新生成的字符串。 (是的,要区分变异和复制之间的区别需要一些练习;是的,将新字符串分配给变量 不是 归类为变异,而是分配一个新字母给该变量中的索引位置。)

    改进

    问题是,您反复丢弃旧的secretWords,并用其中包含越来越多的“_”的副本替换它们。首先,您可能需要在同一个函数内再次引用原始的secretWord(在函数之外它没有改变 - 它在传递给函数时被复制了!)所以总是一个好主意为这种事情创建一个单独的变量。称它为outputdisplayWord 之类的。其次,所有这些复制和丢弃都是低效的。最后,我将向您展示一种使用list comprehension 的方法,如果您还没有遇到它,它是 Python 最优雅的功能之一,并且通常比其等效循环公式更有效.

    displayWord = ''.join(letter if letter in lettersGuessed else '_ ' for letter in word)
    

    就是这样。您可以将displayWord = 替换为return 并具有单行功能。需要明确的是,列表理解部分是[letter if letter in lettersGuessed else '_ ' for letter in word],但这会生成一个列表。要将列表转换为字符串,请使用 ''.join()(在这种情况下,您可以删除列表理解本身的方括号)。

    最后一件事。如果secretWord = "caligula"lettersGuessed = "aei"displayWord 将是_ a_ _ _ u_ a。请注意未插入空格的字母的错位。有一个完美的方法来解决这个问题。您可能想知道 ''.join() 的奇怪语法。我们正在做的是在空字符串上调用join 方法。无论我们调用join 的任何字符串,在将列表粘合在一起时都充当列表项之间的分隔符。因此,如果我们希望我们的displayWord 间隔整齐,我们可以这样写:

    # (note where I've put the space)
    displayWord = ' '.join(letter if letter in lettersGuessed else '_' for letter in word)
    

    【讨论】:

    • 非常感谢。有效!列表理解的想法让我大吃一惊,您提供的帮助解释它的链接也非常有助于巩固我对这个概念的理解。我曾短暂地看到它提到过,但对于我正在上的课程还没有完全解决。我想知道为什么——它似乎在未来非常有用。
    • 我很高兴我设法让你大吃一惊!嗯,列表推导在某些方面是语法糖,因为它浓缩了一个你通常会写成循环的模式。所以在学习进度方面,先学习基于循环的路线当然是好的。另一方面,它不仅仅是语法糖,因为在表面之下,它以循环可能不是的方式进行了优化。它是 Pythonic 风格的一个关键特性,所以任何值得一提的类最终都会接受它。 PS。如果您觉得我的回答有帮助,请考虑采纳。 (点击勾号。):)
    猜你喜欢
    • 2021-01-27
    • 1970-01-01
    • 2021-09-17
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 2021-09-11
    相关资源
    最近更新 更多