3

我不断地将我的 str.join() 参数包装在一个列表中,例如

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

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

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

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

'.'.join(*list_of_strings)

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

编辑:

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

最大值(可迭代[,键])最大值(arg1,arg2,*args[,键])

4

3 回答 3

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 个字符,而在大数据情况下是浪费的。

历史记录

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

*argsin 函数定义是很久以前在 Python 中添加的:

==> 0.9.8 版(1993 年 1 月 9 日)<==

需要案例 (a) 来容纳可变长度的参数列表;现在有一个明确的“可变参数”功能(在最后一个参数之前有一个'*')。为了与旧的类定义兼容,需要案例 (b):直到 0.9.4 版本,必须将具有多个参数的方法声明为 "def meth(self, (arg1, arg2, ...)): .. ."。

将列表传递给此类函数的正确方法是使用内置函数apply(callable, sequence)。(注意,这并没有提到**kwargs哪个可以在1.4 版本的文档中首先看到)。

*在 1.6 的发行说明中首次提到了使用语法调用函数的能力:

现在可以使用特殊语法代替 apply() 函数。f(*args, **kwds) 等价于 apply(f, args, kwds)。您还可以使用变体 f(a1, a2, *args, **kwds),并且可以省略其中一个:f( args), f( *kwds)。

但是直到2.2 版的语法文档中都缺少它。

在 2.0 之前str.join()甚至不存在,您必须这样做from string import join

于 2012-11-09T21:35:32.027 回答
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))

于 2012-11-09T21:21:02.830 回答
2

啊,现在这是一个很难的问题!尝试争论哪种风格更简约......很难在没有太主观的情况下给出一个好的答案,因为这都是关于惯例的。

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


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

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

  • 当可以使用任意数量的单独序列调用函数时- 如zipormapitertools.chain,
  • 当有一个序列要传递时,但您并不真正期望调用者将整个序列作为单个变量。这似乎很合适str.format

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

  • 当您想对单个序列进行一些通用数据处理时。这适合函数式三重奏(map*、reducefilter)和它们的特殊衍生,如sumor str.join。还有像enumerate.
    • 模式是“使用一个可交互对象,给出另一个可迭代对象”或“使用一个可迭代对象,给出一个结果”。

希望这能回答你的问题。


注意:map从技术上讲是 var-arg,但常见的用例是与andmap(func, sequence) -> sequence放在一个桶中。reducefilter

*这个晦涩的案例map(func, *sequences)在概念上类似于map(func, izip_longest(sequences))- zips 遵循 var-arg 约定的原因之前已解释过。

我希望你在这里遵循我的想法;毕竟这都是编程风格的问题,我只是指出 Python 库函数中的一些模式。

于 2012-11-09T21:43:52.270 回答