当前位置:  开发笔记 > 编程语言 > 正文

Python join:为什么是string.join(list)而不是list.join(string)?

如何解决《Pythonjoin:为什么是string.join(list)而不是list.join(string)?》经验,为你挑选了8个好方法。

这一直困扰着我.看起来这会更好:

my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"

比这个:

my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"

是否有这样的具体原因?



1> recursive..:

这是因为任何可迭代都可以连接,而不仅仅是列表,但结果和"连接"总是字符串.

例如:

import urllib2
print('\n############\n'.join(
    urllib2.urlopen('http://data.stackexchange.com/users/7095')))


即使代码有意义,我也不同意概念.`list.join(string)`看起来更像是一种面向对象的方法,而`string.join(list)`对我来说听起来更具程序性.
那么为什么它不能在iterable上实现呢?
我曾尝试使用`print(str.join(' - ',my_list))`并且它有效,感觉更好.
@TimeSheep:整数列表没有有意义的连接,即使它是可迭代的.
@TimeSheep因为iterable不是具体类型,所以iterable是一个接口,任何定义`__iter__`方法的类型.对于一个非常特殊的用例,要求所有迭代也实现`join`会使一般接口(也包括非字符串的迭代)复杂化.在strins端定义`join` - 以"不直观"的顺序为代价来解决这个问题.一个更好的选择可能是保持一个函数,第一个参数是可迭代的,第二个(可选的一个)是连接字符串 - 但是该船已经航行.
@krysopath:它可以*,但有多种这样的理解.字符串的非列表迭代需要一种方法来连接.字符串列表是可迭代的.因此,使用这种方法可以满足所有用例.Lists*可以*有一个连接方法,就像在javascript中一样,但是在python中有很多用例仍然需要现有的连接方法.你可以非常简单地将现有的一个变成你正在思考的东西.例如`",".join(map(str,numbers))`.
@PerLundberg但是_every_ iterable会运行一个`join`方法,即使那些没有意义的方法也是如此.例如,你有一个与文件无关的`file.join`,生成器会有一个与生成器完全无关的`join`方法(对于无限的非常危险).我不熟悉Ruby,但我怀疑它只是将`join()`实现为list方法,而不是每个迭代器上的方法.
@ user4815162342是的,它实际上是在`Array`类上实现的:https://ruby-doc.org/core-2.5.1/Array.html#method-i-join您的推理可能是正确的,可能是他们为什么不选择该路线(以及为什么Ruby也没有选择路线)的一个很好的理由。我想我现在更多地属于这个问题的另一个答案中提到的“许多核心Python程序员”阵营。:-)

2> Yoshiki Shib..:

这是在String方法中讨论的......最终在Python-Dev achive中的线程,并被Guido接受.该线程始于1999年6月,并str.join包含在2000年9月发布的Python 1.6中(并支持Unicode).Python 2.0(str包括支持的方法join)于2000年10月发布.

这个帖子中提出了四个选项:

str.join(seq)

seq.join(str)

seq.reduce(str)

join 作为内置功能

Guido不仅要支持lists,tuples,还要支持所有序列/可迭代.

seq.reduce(str) 新来者很难.

seq.join(str) 引入了从序列到str/unicode的意外依赖.

join()作为内置函数,仅支持特定数据类型.因此使用内置命名空间并不好.如果join()支持许多数据类型,那么创建优化的实现将很困难,如果使用该__add__方法实现,那么它是O(n²).

sep不应省略分隔符字符串().显式优于隐式.

此主题中没有其他原因.

这里有一些额外的想法(我自己和我的朋友):

Unicode支持即将到来,但它不是最终的.那时UTF-8最有可能取代UCS2/4.要计算UTF-8字符串的总缓冲区长度,需要知道字符编码规则.

那时,Python已经决定了一个公共序列接口规则,用户可以创建一个类似序列(可迭代)的类.但是Python不支持在2.2之前扩展内置类型.那时很难提供基本的可迭代类(在另一条评论中提到).

Guido的决定记录在历史邮件中,决定str.join(seq):

有趣,但看起来确实对!巴里,去吧... -
Guido van Rossum



3> Bill Karwin..:

因为该join()方法是在字符串类中,而不是列表类?

我同意它看起来很有趣.

请参阅http://www.faqs.org/docs/diveintopython/odbchelper_join.html:

历史记录.当我第一次学习Python时,我希望join是一个列表的方法,它将分隔符作为参数.很多人都有同样的感觉,加入方法背后有一个故事.在Python 1.6之前,字符串没有所有这些有用的方法.有一个单独的字符串模块,其中包含所有字符串函数; 每个函数都将一个字符串作为其第一个参数.这些函数被认为足够重要,可以放在字符串本身,这对于lower,upper和split等函数有意义.但许多硬核Python程序员反对新的连接方法,认为它应该是列表的方法,或者它根本不应该移动,而只是保留旧的字符串模块的一部分(仍然有很多有用的东西在它).

--- Mark Pilgrim,潜入Python


Python 3`字符串`库删除了所有冗余的`str`方法,因此你不再可以使用`string.join()`.就个人而言,我从来没有想过它"有趣",它是完全合理的,因为你可以加入的不仅仅是列表,但木匠总是一个字符串!

4> Kiv..:

我同意它起初是违反直觉的,但这是有充分理由的.加入不能是列表的方法,因为:

它必须适用于不同的迭代(元组,生成器等)

它必须在不同类型的字符串之间具有不同的行为.

实际上有两种连接方法(Python 3.0):

>>> b"".join

>>> "".join

如果join是列表的方法,那么它必须检查其参数以决定调用哪一个.并且你不能将byte和str连接在一起,所以他们现在拥有它的方式是有道理的.



5> Aaron Hall..:
为什么不string.join(list)代替list.join(string)

这是因为join是一个"字符串"方法!它从任何可迭代创建一个字符串.如果我们把方法放在列表上,那么当我们有不是列表的迭代时呢?

如果你有一个字符串元组怎么办?如果这是一个list方法,那么在将list元素连接成单个字符串之前,必须将每个这样的字符串迭代器强制转换为一个方法!例如:

some_strings = ('foo', 'bar', 'baz')

让我们滚动我们自己的列表连接方法:

class OurList(list): 
    def join(self, s):
        return s.join(self)

要使用它,请注意我们必须首先从每个iterable创建一个列表来连接该iterable中的字符串,从而浪费内存和处理能力:

>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'

所以我们看到我们必须添加一个额外的步骤来使用我们的list方法,而不是仅使用内置字符串方法:

>>> ' | '.join(some_strings) # a single step!
'foo | bar | baz'

发电机性能警告

Python用来创建最终字符串的算法str.join实际上必须通过迭代两次,所以如果你提供一个生成器表达式,它必须首先将它实现为一个列表,然后才能创建最终的字符串.

因此,虽然绕过生成器通常比列表推导更好,str.join但是例外:

>>> import timeit
>>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
3.839168446022086
>>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
3.339879313018173

尽管如此,str.join操作在语义上仍然是一个"字符串"操作,因此将它放在str对象上比使用其他迭代更有意义.



6> Andy Dent..:

将其视为分裂的自然正交操作.

我明白为什么它适用于任何可迭代的,所以不能简单地执行只是在列表中.

为了便于阅读,我想在语言中看到它,但我不认为这实际上是可行的 - 如果迭代是一个接口,那么它可以添加到接口但它只是一个约定,所以没有中心的方法将它添加到可迭代的事物集中.



7> S.Lott..:

主要是因为a的结果someString.join()是一个字符串.

序列(列表或元组或其他)不会出现在结果中,只是一个字符串.因为结果是一个字符串,所以它作为字符串的方法是有意义的.



8> Algebra..:

- 在" - "中,join(my_list)声明你要转换为一个字符串,从连接元素列表.它是面向结果的.(只是为了方便记忆和理解)

我为methods_of_string制作了详尽的备忘单供您参考.

string_methonds_44 = {
    'convert': ['join','split', 'rsplit','splitlines', 'partition', 'rpartition'],
    'edit': ['replace', 'lstrip', 'rstrip', 'strip'],
    'search': ['endswith', 'startswith', 'count', 'index', 'find','rindex', 'rfind',],
    'condition': ['isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isnumeric','isidentifier',
                  'islower','istitle', 'isupper','isprintable', 'isspace', ],
    'text': ['lower', 'upper', 'capitalize', 'title', 'swapcase',
             'center', 'ljust', 'rjust', 'zfill', 'expandtabs','casefold'],
    'encode': ['translate', 'maketrans', 'encode'],
    'format': ['format', 'format_map']}

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有