这一直困扰着我。看起来这样更好:
1 2 3 | my_list = ["Hello","world"] print my_list.join("-") # Produce:"Hello-world" |
比这个:
1 2 3 | my_list = ["Hello","world"] print"-".join(my_list) # Produce:"Hello-world" |
有什么特别的原因吗?
这是因为任何可迭代的都可以连接,不仅仅是列表,结果和"joiner"都是字符串。
例句:
1 2 3 4 5 | import urllib2 print ' ############ '.join( urllib2.urlopen('http://data.stackexchange.com/users/7095')) |
这在String方法中讨论过…最后线程在Python-Dev中实现,并被圭多接受。这个线程开始于1999年6月,
本帖中没有提供其他原因。
以下是一些额外的想法(我自己的,我朋友的):
Unicode支持即将到来,但它不是最终的。当时UTF-8最有可能取代UCS2/4。为了计算UTF-8字符串的总缓冲区长度,需要知道字符编码规则。那时,Python已经决定了一个公共序列接口规则,在这个规则中,用户可以创建一个类似于序列的(可迭代的)类。但是Python直到2.2才支持扩展内置类型。当时很难提供基本的可迭代类(另一条评论中提到了这一点)。Guido的决定记录在历史邮件中,决定
Funny, but it does seem right! Barry, go for it...
--Guido van Rossum
因为
我同意这看起来很有趣。
见http://www.faqs.org/docs/diveintopython/odbchelper_join.html。
Historical note. When I first learned
Python, I expected join to be a method
of a list, which would take the
delimiter as an argument. Lots of
people feel the same way, and there’s
a story behind the join method. Prior
to Python 1.6, strings didn’t have all
these useful methods. There was a
separate string module which contained
all the string functions; each
function took a string as its first
argument. The functions were deemed
important enough to put onto the
strings themselves, which made sense
for functions like lower, upper, and
split. But many hard-core Python
programmers objected to the new join
method, arguing that it should be a
method of the list instead, or that it
shouldn’t move at all but simply stay
a part of the old string module (which
still has lots of useful stuff in it).
I use the new join method exclusively,
but you will see code written either
way, and if it really bothers you, you
can use the old string.join function
instead.--- Mark Pilgrim, Dive into Python
我同意一开始这是违反直觉的,但有一个很好的理由。Join不能是列表的方法,因为:
它还必须适用于不同的迭代器(元组、生成器等)。它必须在不同类型的字符串之间具有不同的行为。实际上有两种连接方法(Python 3.0):
1 2 3 4 | >>> b"".join <built-in method join of bytes object at 0x00A46800> >>>"".join <built-in method join of str object at 0x00A28D40> |
如果join是一个列表的方法,那么它必须检查它的参数来决定调用哪个参数。你不能把byte和str连接在一起,所以它们现在的方式是有意义的。
Why is it string.join(list) instead oflist.join(string) ?
这是因为
如果你有一个字符串元组呢?如果这是一个
1 | some_strings = ('foo', 'bar', 'baz') |
让我们滚动我们自己的列表连接方法:
1 2 3 | class OurList(list): def join(self, s): return s.join(self) |
要使用它,请注意,我们必须首先从每个iterable创建一个列表来连接该iterable中的字符串,浪费内存和处理能力:
1 2 3 | >>> l = OurList(some_strings) # step 1, create our list >>> l.join(', ') # step 2, use our list join method! 'foo, bar, baz' |
所以我们看到我们必须添加一个额外的步骤来使用我们的列表方法,而不是仅仅使用内建字符串方法:
1 2 | >>> ' | '.join(some_strings) # a single step! 'foo | bar | baz' |
生成器的性能警告
Python用来创建带有
因此,虽然传递生成器通常比列表理解更好,但
1 2 3 4 5 | >>> 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 |
然而,
把它看作是自然的正交运算。
我理解为什么它适用于任何可迭代的东西,所以不能简单地在列表中实现。
可读性,我想看看它的语言但我不认为这是可行的——如果iterability接口就可以添加到接口,但它只是一个会议,所以没有中央的方法将其添加到组东西iterable。
主要是因为
序列(列表或元组或其他)不会出现在结果中,只是一个字符串。因为结果是一个字符串,所以它作为一个字符串的方法是有意义的。
我做了一个详尽的methods_of_string作弊表供您参考。
1 2 3 4 5 6 7 8 9 10 | 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']} |
两者都不好。
字符串。join(xs, delimit)意味着字符串模块知道列表的存在,它不需要知道列表的存在,因为字符串模块只处理字符串。
join(delimit)更好一些,因为我们已经习惯了字符串是一种基本类型(从语言上讲,它们确实是)。然而,这意味着join需要动态地分派,因为在
")
如果python运行时编译器知道列表是一个建在模块,它可以跳过动态查找和编码意图直接到字节码,而否则需要动态地解决"a"的"加入",这可能是几层的每个电话inheritence(自之间的调用,加入的意义可能已经改变了,因为python是一种动态语言)。
遗憾的是,这是抽象的最终缺陷;无论你选择什么抽象,抽象的背景下才有意义你想解决的问题,这样你可以没有一个一致的抽象,不成为符合潜在的意识形态开始粘合在一起没有包装在一个视图,和你的思想是一致的。知道了这一点,python的方法就更灵活了,因为它更便宜,您可以花更多的钱来让它看起来"更好",可以通过自己制作包装器,也可以使用自己的预处理器。