这是我提出的方式:
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')
。这种方法有什么问题?
答案 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)]
无论哪种方式,结果都会根据需要解压缩到变量a
和b
。
您可能需要考虑推广该函数,以便它接受任意数量的参数:
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开始。