循环语句 - 不同的答案

时间:2013-06-16 03:06:30

标签: python python-3.x while-loop

以此函数为例。

def spaced_word(s):
    i= 0
    t = s[i] + ' '

    while i < len(s) - 2:
        t = t + s[i + 1] + ' '
        i = i + 1
    t= t + s[len(s) - 1]
    return t

此函数返回在每个字符之间输入空格的字符串。 (例如spaced_word('hello') - &gt; 'h e l l o'

但是,为什么有必要使用t = t + ...作为陈述?

例如,为什么我不能只使用:

s[i] + ' '
i = i + 1

另外,如果我替换行

,为什么不会出现相同的结果
t = t + s[i + 1] + ' '

s[i] + ' ' + s[i + 1] + ' '

t = s[i] + ' '

解决。谢谢所有帮助过的人!

3 个答案:

答案 0 :(得分:2)

您的问题似乎是为什么您需要维护一个单独的t变量来保存字符串,而不是直接更改其值。

原因是Python的字符串是不可变的。您不能在现有字符串的两个字母之间插入空格,因为您无法修改该字符串的内容。您想要进行的任何修改都必须通过创建包含原始字符串字符副本的新字符串来完成。

您询问的代码行t = t + " " + s[i+1]执行以下操作:

  1. 首先,它创建一个新字符串,其中包含前一个值t的副本,其中一个空格连接到末尾。这是一个临时值,不绑定任何变量名。
  2. 然后创建第二个新字符串,复制步骤1中的字符串并将s中的字符连接到结尾。 Python可能足够聪明,可以重用第一步中的临时字符串,而不是复制它,但这通常不是你可以依赖的。
  3. 最后,上面步骤2创建的字符串绑定到变量t,替换那里的旧字符串(将被垃圾收集,因为没有其他引用)。
  4. 您建议的替代代码s[i + 1] + " "会创建一个新字符串,但它不会对其执行任何操作。它没有分配给任何东西,因此它将立即被垃圾收集。重要的是要了解s[i+1] + " "不会更改字符串s。即使尝试使用不同的语法,例如s[i+1] += " "它也行不通,但在这种情况下你会得到一个例外。

    这是一个稍微更多的Pythonic版本的代码,可能会使其功能更加清晰:

    def spaced_words(s):
        result = s[0]           # start with the first letter of the string
        for c in s[1:]:         # iterate over the rest of the string
            result += " " + c   # add a space and the next character to the result
        return result           # when the loop is done, return the result string
    

    for循环替换了代码中的while循环和显式索引。这更容易遵循。我也在使用+=运算符,而不是result = result + otherstuff,但这实际上并不是主要区别。由于result字符串是不可变的,因此每次将新值连接到结尾时,通常都需要复制它。但是,CPython(你从python.org获得的常规解释器)有一些特殊的逻辑用于以这种方式附加到字符串,并且实际上将避免在大多数时间复制字符串。这是一个实现细节,而不是你应该依赖的东西。

    最后,我想建议使用内置的str.join方法来更轻松,更有效地执行当前函数的工作。它接受任何可迭代对象作为其参数,并且方便地,字符串是其字符的可迭代:

    def spaced_word(s):
        return " ".join(s)
    

    我意识到这不是你的问题,但是了解Python的内置功能是很好的,它几乎总能比你自己编写的代码做得更好。

答案 1 :(得分:1)

我没有详细查看您的代码,但是有一个很多更简单的方法来编写您正在讨论的函数:

def spaced_word( s ):
    return ' '.join( s )

print spaced_word( 'abcde' )

打印:

a b c d e

编辑:好的,现在我看了你的代码,看看我能否回答你的问题,答案是否定的,我不能。那段代码太复杂了。 (对不起!)这是一种代码,其中复杂性应该让你退后一步并问:“有没有更简单的方法来做到这一点?”

这样说我不仁慈吗?如果是这样,我真诚地道歉。但有时你只需要抛弃你的代码并重新开始使用更简单的方法。是的,我从谦卑的个人经历中知道这一点,抛出了我自己代码的很多

一些危险信号:

  • 将两个空格附加到输出字符串

  • 有两个不同的位置
  • 三个不同的地方,其中一个字符被附加到输出。字符串的第一个字符得到特殊处理,最后一个字符也是如此。

  • 一个运行到字符串长度减去两个的循环。

在Python中,就像Ruby和JavaScript以及其他一些语言一样,当你需要在其他一些项目之间插入一些东西时,最后没有额外的“东西”,首先要看的是{{ 1}}函数或方法。在每种语言中,它采用数组并在每个数组元素之间插入一个字符串。这是进行此类操作的好方法。

鉴于此,剩下的唯一事情是将原始字符串转换为数组(Python中的列表)。你这样做的方式各不相同。在Python中,您可以使用join() - 尽管您甚至不需要这样做,因为Python字符串是可迭代的,您可以直接对它们执行list(string),就像使用Python列表一样。 (感谢@Blckknght指出这一点。)在Ruby或JavaScript中,它是join - 有趣的是,这两种语言的语法是相同的。

然后,您只需获取结果,并使用该语言的相应语法对其执行string.split('')。这三种语言的代码非常相似。

红宝石:

join(' ')

JavaScript的:

def spaced_word( s )
    s.split('').join(' ')
end

的Python:

function spacedWord( s ) {
    return s.split('').join(' ');
}

或者使其与其他两种语言更相似:

def spaced_word( s ):
    return ' '.join( s )

这提出了一个(希望)有趣的观点。我对Python代码的第一种方法是使用显式def spaced_word( s ): return ' '.join( list(s) ) 的第二个版本。我最近一直在使用JavaScript,Python和Ruby进行编码,但大多数情况下,上周大部分都是JavaScript。因此,当我编写一些Python代码时,我自然而然地陷入了一种更加JavaScript风格的方法:首先将字符串转换为数组(列表),然后在其上调用list(s)。在JavaScript中,您无法直接在字符串上调用join。但是在Python中你可以!

也许你的代码中发生了类似的事情?你用一个仔细的逐个字符循环编写它的方式就是用C语言和其他一些语言来实现的。将编码模式从一种语言转移到另一种语言是一种自然的趋势,就像我从JavaScript思维模式中编写Python代码一样。

对于我自己,我知道我必须不断地对抗这一点,并根据我目前编写的语言和它提供的功能进行思考。 Python,以及Ruby和JavaScript以及其他类似语言,提供了丰富的字符串和数组/列表操作函数,因此在编写自己的更详细代码之前,需要先查看它。

答案 2 :(得分:-1)

在内存变量s

有一个像'hello'这样的值意味着s ='hello'

你在内存变量't'中存储的值高于每个带空格的字母

s[i] + ' ' + s[i + 1] + ' '
s[1] = ' ' + s[1 + 1] + ' '
s[1] = ' ' + h        + ' '
s[1] = ' h '    // here you are getting space before & after  s[1 + 1]

所以你的结果就像'h e l l o'

while t = t + s[i + 1] + ' '
gives result 'h e l l o '