Python:为什么str.join(iterable)而不是str.join(* strings)

时间:2012-11-09 21:16:36

标签: python

我经常在列表中包装我的str.join()参数,例如

'.'.join([str_one, str_two])

额外的列表包装对我来说似乎总是多余的。我想做...

'.'.join(str_one, str_two, str_three, ...)

......或者如果我有一个清单......

'.'.join(*list_of_strings)

是的我是一个极简主义者,是的我挑剔,但大多数时候我只是对这里的历史感到好奇,或者我是否遗漏了什么。也许在splats之前有一段时间?

编辑:

我只想指出max()处理两个版本:

max(iterable [,key]) max(arg1,arg2,* args [,key])

3 个答案:

答案 0 :(得分:4)

对于简短列表,这无关紧要,只需输入2个字符。但str.join()最常见的用例(我认为)如下:

''.join(process(x) for x in some_input) 
# or
result = []
for x in some_input:
    result.append(process(x))
''.join(result)

其中input_data可以包含数千个条目,您只想有效地生成输出字符串。

如果连接接受变量参数而不是迭代,则必须将其拼写为:

''.join(*(process(x) for x in some_input))
# or
''.join(*result)

会创建一个(可能很长的)元组,只是将其作为*args传递。

因此,在短数据中,这是2个字符,而在大数据情况下则是浪费。

历史记录

(第二次编辑:基于HISTORY文件,其中包含所有版本中缺少的版本。感谢Don。)

很久以前,Python中添加了函数定义中的*args

  

==>发布0。9。8(1993年1月9日)< ==

     

需要案例(a)来容纳可变长度的参数列表;   现在有一个明确的“varargs”功能(在最后一个参数之前)   用'*')。案例(b)是与旧班级兼容所必需的   定义:最多释放0.9.4一个带有多个参数的方法   必须被宣布为“def meth(self,(arg1,arg2,...)):...”。

将列表传递给此类函数的正确方法是使用内置函数apply(callable, sequence)。 (注意,这并未提及**kwargs中可以首先看到的*

在1.6的发行说明中首次提到了使用str.join()语法调用函数的能力:

  

现在可以使用特殊语法代替apply()   功能。 f(* args,** kwds)相当于apply(f,args,kwds)。您   也可以使用变量f(a1,a2,* args,** kwds),你可以留下一个   或者其他:f( args),f( * kwds)。

但是docs for version 1.4直到missing from grammar docs

2.0之前from string import join甚至不存在,你必须{{1}}。

答案 1 :(得分:2)

你必须编写自己的功能才能做到这一点。

>>> def my_join(separator, *args):
        return separator.join(args)

>>> my_join('.', '1', '2', '3')
'1.2.3'

请注意,这不会避免创建额外的对象,只是隐藏正在创建一个额外的对象。如果你检查args的类型,你会发现它是tuple

如果你不想创建一个函数并且你有一个固定的字符串列表,那么就可以使用format而不是join:

'{}.{}.{}.{}'.format(str_one, str_two, str_three, str_four)

最好坚持'.'.join((a, b, c))

答案 2 :(得分:2)

唉,现在这是个难题!尝试争论哪种风格更简约......难以给出一个好的答案,而不是太主观,因为这完全是关于惯例。

问题是:我们有一个接受有序集合的函数;它应该接受它作为单个参数还是可变长度参数列表?


Python通常会回答:单个参数; VLAL,如果你真的有理由。让我们看看Python库如何反映这一点:

标准库有几个VLAL示例,最值得注意的是:

  • 当使用任意数量的单独序列调用该函数时 - 例如zipmapitertools.chain
  • 当有一个序列要通过时,但你真的不希望调用者将整个序列作为单个变量。这似乎适合str.format

使用单个参数的常见情况:

  • 当您想对单个序列进行一些通用数据处理时。这符合功能三重奏(map *,reducefilter)及其专业产生,例如sumstr.join。同样有状态的转换如enumerate
    • 模式是“消耗一个可交换的,给另一个可迭代的”或“消耗一个可迭代的,给出一个结果”。

希望这能回答你的问题。


注意:map在技术上是var-arg,但常见用例只是map(func, sequence) -> sequence,它属于reducefilter的一个存储桶。< / em>的

*晦涩的案例,map(func, *sequences)在概念上与map(func, izip_longest(sequences))相似 - 之前解释了zip遵循var-arg惯例的原因。

我希望你能在这里思考;毕竟这都是编程风格的问题,我只是指着Python库函数中的一些模式。