连接时在非空情况下添加分隔符到末尾

3 投票
4 回答
14984 浏览
提问于 2025-04-17 12:09

我需要把所有的元素都加到一个string里;最后还要加一个后缀。所有元素之间要用一个点 '.' 来分隔:

list_ = args[f(n) : f(n+1)]
if list_:
  string += '.' + '.'.join(list_) + '.' + suffix # works except when list_ is empty
else:
  string += '.' + suffix
# list_ isn't used after this

我能不能用更简单的一行代码来写这个?如果join在每个元素后面加一个分隔符,那就可以这样写:

string += '.' + '.'.join(args[f(n) : f(n+1)]) + '.' + suffix

编辑

我刚刚了解到:

切片是复制,即使它们从未被赋值给其他变量:Python在字符串上做切片时是引用吗?

但是islice可能更糟,因为它会从列表的开头开始迭代:itertools.islice与列表切片的比较

这里讨论了一些替代方案:在Python中避免不必要的切片复制

4 个回答

4

如果list_是一个生成器(或者可以很简单地变成一个生成器),你可以使用itertools里的chain(),完全不需要创建任何列表。

from itertools import chain
'.'.join(chain(('',),list_,(suffix,)))

(这个想法来源于David Zaslavsky的回答。)

4

还有一点可以参考David Zaslavsky的回答

string = '.'.join([string] + list_ + [suffix])

这样做的好处是,不会有字符串的相加

5

我会选择这个(更新以反映问题的修改):

'.'.join([''] + args[f(n):f(n+1)] + [suffix])

编辑:受到sblom和unutbu回答的启发,我可能实际上会这样做:

from itertools import chain, islice
string = '.'.join(chain([string],  islice(args, f(n), f(n+1)), [suffix]))

如果我担心切片args的内存开销。你可以用一个元组(string,)或者一个列表[string]来表示字符串和后缀;因为它们各只有一个元素,所以在内存使用和执行时间上没有显著的差别,而且由于它们不是被存储的,你也不需要担心可变性。我觉得列表的写法看起来更简洁。

不过:我不确定Python是否真的会为一个只会被使用而不会被赋值的切片创建一个新的列表对象。如果没有,那么考虑到args是一个合适的列表,使用islice而不是[f(n):f(n+1)]并不会给你节省太多东西,在这种情况下我会选择简单的方法(上面提到的)。如果args是一个生成器或者其他惰性求值的可迭代对象,并且元素数量非常大,那么那时候使用islice可能就值得了。

撰写回答