如何遍历字符串列表,操作一些字符串操作并返回它们?

时间:2017-09-06 03:02:34

标签: python regex function

这是我提出的方式:

a = 'bats bear'
b = 'cats pear'

def sub_strings(a, b):
    for s in [a, b]:
        s = re.sub('\\b.ear\\b', '', s)  
    return a, b

a, b = sub_strings(a, b)

但这根本不起作用,该函数仍然输出原始字符串('bats bear', 'cats pear')。这种方法有什么问题?

3 个答案:

答案 0 :(得分:4)

s = re.sub('\\b.ear\\b', '', s) 

不符合您的想法。它只是将名为s的变量重新绑定re.sub()返回的修改后的字符串。它不会改变变量a也不会改变b。您可以通过在循环中打印出s的值来检查。

相反,您可以返回生成器:

def sub_strings(a, b):
    return (re.sub(r'\b.ear\b', '', s) for s in (a, b))

列表理解也有效:

def sub_strings(a, b):
    return [re.sub(r'\b.ear\b', '', s) for s in (a, b)]

无论哪种方式,结果都会根据需要解压缩到变量ab

您可能需要考虑推广该函数,以便它接受任意数量的参数:

def sub_strings(*args):
    return (re.sub(r'\b.ear\b', '', s) for s in args)

现在你可以使用任意数量的参数调用它:

>>> print(list(sub_strings('bats bear', 'cats pear', 'rats hear')))
['bats ', 'cats ', 'rats ']
>>> print(list(sub_strings('bats bear', 'cats pear', 'rats hear', 'gnats rear')))
['bats ', 'cats ', 'rats ', 'gnats ']

答案 1 :(得分:1)

试试这个

a = 'bats bear'
b = 'cats pear'

def sub_strings(a, b):
    result = []
    for s in [a, b]:
        result.append(re.sub('\\b.ear\\b', '', s)  )
    return result[0], result[1]

a, b = sub_strings(a, b)

答案 2 :(得分:1)

您遇到的问题是,在Python中,字符串(即str类型对象)是不可变对象。由于无法更改字符串对象,因此对字符串执行的任何功能都不会更改原始字符串 始终 保持不变:

>>> s = 'abc'
>>> s.replace('abc', 'def') #  perform some method on s
>>> print(s) #  has s been changed?
abc # NOPE

如果您想获得字符串的操作版本,则必须将操纵版本保存在某处并返回 THAT 。已经提供的其他答案清楚地显示了如何做到这一点。

至于你的实际问题,我建议使用发电机。生成器是一种与正常函数非常不同的函数。其中一个区别是生成器函数能够一次生成多个结果 - 只需一个函数调用。

要创建生成器,而不是使用单词return,请使用yield。这是一个例子:

a = 'bats bear'
b = 'cats pear'

def sub_string_gen(*strings):
    for s in strings:
        yield re.sub('\\b.ear\\b', '', s)  

a, b = sub_strings(a, b) #  generator is "unpacked" here

请注意,*strings语法允许函数接受多个参数。您的函数内的参数在名称为strings的列表下可用。

上面代码工作的原因是最后一行自动神奇地执行你执行的生成器的UNPACKING。换句话说,每次产生一个结果,并一次一个地解压缩到相应的提供名称中。

但要小心,你不要试图这样做:

a = sub_strings(a) #  BAD!

这不会按照您的预期工作。它不起作用,因为a = sub_strings(a)没有解包生成器;而是创建生成器,分配给a;发电机尚未拆包。澄清术语:sub_strings生成器函数; sub_strings(a,b,c) 使用生成器函数创建 生成器

要将生成器解压缩为单个名称,请执行以下操作:

a, = sub_strings(a) #  Note the comma

额外的逗号使a成为符号元组而不是单符号。这让口译员知道你的意思是打开"解包"将生成器转换为孤立符号a

我非常喜欢这种语法,因为它可以防止你制作并不容易看到的错误。例如,如果您为sub_strings提供了太多参数但没有足够的变量,它会给您一个错误并让您知道存在问题:

>>> a, b = sub_strings(a, b, c) #  extra c argument
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

使用生成器的另一种方法是简单地将结果填充到列表,元组或任何接受可迭代对象的任何其他内容中(生成器是可迭代的):

>>> results = list(sub_strings(a, b, c, d, e, f))

还有另一种非常好的替代语法可以做同样的事情。在这里,我们再次看到那颗星(有些人称之为&#34; splat&#34;)。 splat&#34;解包&#34;生成器一次一个值,与之前自动解压缩的值非常相似:

>>> results = [*sub_strings(a, b, c, d, e, f)]

最后:你甚至不必定义一个生成发电机的功能。您只需使用所谓的generator expression即可。

>>> a, b = (re.sub('\\b.ear\\b', '', s)  for s in (a, b))

您可以在我们上面使用我们的生成器的任何地方使用这样的表达式:

>>> results = list((re.sub('\\b.ear\\b', '', s)  for s in (a, b)))
>>> results = [*(re.sub('\\b.ear\\b', '', s)  for s in (a, b))]

观察名为生成器表达式 的部分替换生成器函数调用 - 它在先前版本的代码中创建生成器。

但是,如果您的目标是list,则更短的语法就是使用所谓的列表理解:

>>> results = [re.sub('\\b.ear\\b', '', s)  for s in (a, b)]

要学习Python生成器还有很多东西。开始here开始。