我在 for 循环和 return 语句中一直犯的一个错误

Posted

技术标签:

【中文标题】我在 for 循环和 return 语句中一直犯的一个错误【英文标题】:a mistake I keep having with for loops and return statements 【发布时间】:2017-02-24 09:39:29 【问题描述】:

每当我尝试创建一个函数来更改字符串或列表然后返回它时,我一直注意到我遇到的问题。

我会用我刚刚写的代码给你一个例子:

def remove_exclamation(string):
string.split(' ')
for i in string:
    i.split()
    for char in i:
        if char == '!':
            del char
            ''.join(i)
            ' '.join(string)
return string

例如,我创建此代码以将字符串作为其参数,删除其中的任何感叹号,返回它改变了。输入和输出应该是这样的:

>>>remove_exclamation('This is an example!')
'This is an example'

但是我得到了这个:

>>>remove_exclamation('This is an example!')
'This is an example!'

该函数没有删除输出中的感叹号,也没有按照我今天的意图进行。

当我制作 for 循环、嵌套 for 循环等时,如何避免这种情况?

【问题讨论】:

您的两个输出都是相同的。但是您缺少的是将string.split(',') 重新绑定到string。你看,字符串在 python 中是不可变的。 既然有str.replace,为什么还要经历这么多麻烦? 你的一个问题是你正在做i.split(),而你应该做i = i.split()。在您的代码中,结果永远不会分配给任何东西。 您的代码注定要失败,因为您从未分配任何操作的结果。此外,您的缩进已关闭,我不确定您是否知道 del char 的作用。 是的,list.joinstr.split,——实际上是所有字符串方法——返回一个新值。他们不会就地修改数据。即使假设这是真的,您的代码逻辑也已关闭,但您应该从那里开始。 【参考方案1】:

您编写代码并提出问题,就好像可以在 Python 中修改字符串一样。 这是不可能的。

字符串是不可变的。所有对字符串进行操作的函数都返回新字符串。它们不会修改现有字符串。

这会返回一个字符串列表,但您没有使用结果:

string.split(' ')

这也是:

i.split()

这将删除名为char 的变量。它不会影响字符本身:

        del char

这会创建一个您不使用的新字符串:

        ''.join(i)

这也是:

        ' '.join(string)

总而言之,几乎每一行代码都是错误的。

你可能想这样做:

def remove_exclamation(string):
    words = string.split(' ')
    rtn_words = []
    for word in words:
        word_without_exclamation = ''.join(ch for ch in word if ch != '!')
        rtn_words.append(word_without_exclamation)
    return ' '.join(rtn_words)

但最后,这也是同样的事情:

def remove_exclamation(string):
    return string.replace('!', '')

【讨论】:

如果您只想删除单个字符,则无需用空格分割字符串 -- ''.join(ch for ch in string if ch != '!') 就足够了(如果您不想使用 string.replace)跨度> @AndreaCorbellini 当然。这个例子的目的是用最小的改动来修复原始函数,以便解释如何使用str.splitstr.join的结果。【参考方案2】:

没有清楚地知道你的功能的意图和你试图做什么。对于 zvone 给出的答案,我有一个替代方案。

此选项用于删除您未在允许的字符列表中定义的任何字符:

characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "

test_string = "This is an example!"

test_string = ''.join(list(filter(lambda x: x in characters, test_string)))

print(test_string)

这个输出:

这是一个例子

注意,这是 Python 3 版本。

Python 2,你不需要''.join(list())

这样做可以让你定义任何你不想出现在你的字符串中的字符,并且它会删除它们。

你甚至可以反过来做:

ignore_characters= "!"

test_string = "This is an example!"

test_string = ''.join(list(filter(lambda x: x not in ignore_characters, test_string)))

print(test_string)

【讨论】:

您也不需要在 Python 3 中调用 liststr.join 接受任何可迭代对象。 另外,您可以只使用filter(str.isalnum, test_string),或者至少使用set 作为容器而不是另一个字符串。【参考方案3】:

字符串在 Python 中是不可变的。你不能改变它们。但是,您可以在那里重新分配值。

这就是你的问题所在。当您对字符串调用 .split() 时,您永远不会重新分配字符串的值。

但您的程序中也存在其他错误,例如:

你的缩进 事实上,您只是返回传递给函数的字符串 您对del 语句的使用 等

相反,通过遍历旧字符串并通过列表解析和''.join() 过滤掉您不想要的字符来创建一个新字符串。

def remove_exclamation(string):
    return ''.join([char for char in string if char != '!'])

但是正如@Moses 在 cmets 中已经说过的,为什么不直接使用str.replace()?:

string = string.replace('!', '')

【讨论】:

【参考方案4】:
def remove_exclamation(string):

    #you think you are splitting string into tokens
    #but you are not assigning the split anywhere...
    string.split(' ')

    #and here you are cycling through individual _chars_ in string which was not affected by the split above ;-)
    for i in string:
        #and now you are splitting a 1-char string and again not assigning it.
        i.split()

string 仍然是您的输入参数,我假设它属于type str。并且不可变。

最重要的是,如果您正在导入/使用string 模块,您将隐藏它

您的困惑的很大一部分是知道方法何时改变对象以及何时返回新对象。在字符串的情况下,它们永远不会发生变异,您需要将结果分配给一个新变量。

然而,在列表中,join() 某处让我认为您想使用列表,然后方法通常会更改对象。

不管怎样,关于你的问题:

def remove_exclamation(inputstring, to_remove="!"):
    return "".join([c for c in inputstring if c != to_remove])

print (remove_exclamation('This is an example!'))

输出:This is an example

【讨论】:

以上是关于我在 for 循环和 return 语句中一直犯的一个错误的主要内容,如果未能解决你的问题,请参考以下文章

for循环中缺少return语句

return 语句中的 for 循环

新手常犯的错误

break continue return

如何在 for 循环中使用 return 语句?

return break 和continue在for循环中的不同作用