这一直使我感到困惑。看起来这样会更好:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
比这个:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
是否有特定原因?
str
要比在每种可迭代类型上实现起来容易。
这一直使我感到困惑。看起来这样会更好:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
比这个:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
是否有特定原因?
str
要比在每种可迭代类型上实现起来容易。
Answers:
这是因为任何可迭代项都可以连接(例如,列表,元组,字典,集合),但是结果和“连接器” 必须是字符串。
例如:
'_'.join(['welcome', 'to', 'stack', 'overflow'])
'_'.join(('welcome', 'to', 'stack', 'overflow'))
'welcome_to_stack_overflow'
使用字符串以外的其他东西会引发以下错误:
TypeError:序列项0:预期的str实例,找到的int
list.join(string)
看起来更像是一种面向对象的方法,而string.join(list)
对我来说听起来更具有程序性。
print(str.join('-', my_list))
它,并且效果更好。
__iter__
方法的类型。对于所有join
非常特殊的用例,要求所有可迭代对象也要实现将使通用接口(也包括非字符串上的可迭代对象)复杂化。定义join
链约束以“不直观”的命令为代价来绕开此问题。更好的选择可能是保留它的功能,第一个参数是可迭代的,第二个参数(可选的)是连接符字符串-但该船已经驶过。
这在String方法中进行了讨论……最终在Python-Dev中实现,并被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
作为内置功能list
s,tuple
s,而且还支持所有序列/可迭代对象。seq.reduce(str)
对于新来者来说很难。seq.join(str)
从序列到str / unicode引入了意外的依赖关系。join()
因为内置函数仅支持特定的数据类型。因此,使用内置的名称空间是不好的。如果join()
支持许多数据类型,则创建优化的实现将很困难,如果使用该__add__
方法实现,则为O(n²)。sep
)不应省略。显式胜于隐式。此线程中没有其他原因。
以下是一些其他想法(我自己和我朋友的想法):
Guido的决定记录在历史邮件中,决定str.join(seq)
:
有趣,但看起来确实正确!巴里,去吧...-
吉多·范·罗苏姆(Guido van Rossum)
因为该join()
方法位于字符串类中,而不是列表类中?
我同意这看起来很有趣。
参见http://www.faqs.org/docs/diveintopython/odbchelper_join.html:
历史记录。当我第一次学习Python时,我期望join是一个列表方法,它将分隔符作为参数。很多人都有相同的感觉,join方法背后还有一个故事。在Python 1.6之前,字符串没有所有这些有用的方法。有一个单独的字符串模块,其中包含所有字符串函数。每个函数都将字符串作为第一个参数。这些功能被认为很重要,足以放在字符串本身上,这对于诸如lower,upper和split这样的功能是有意义的。但是许多铁杆Python程序员反对使用新的join方法,认为它应该是列表的方法,或者根本不应该移动,而只是保留旧字符串模块的一部分(仍然有很多方法)里面有用的东西)。
--- Mark Pilgrim,深入Python
string
库删除了所有冗余str
方法,因此您不再可以使用string.join()
。就我个人而言,我从来没有想过它是“有趣的”,它很有意义,因为您不仅可以连接列表,还可以连接,但连接器始终是字符串!
我同意起初这是违反直觉的,但是有充分的理由。Join不能成为列表的方法,因为:
实际上有两种连接方法(Python 3.0):
>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>
如果join是列表的一种方法,则它必须检查其参数以确定要调用的参数。而且您不能将byte和str结合在一起,因此它们现在的用法很有意义。
为什么用它
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)
并使用它,请注意,我们必须首先从每个可迭代对象创建一个列表,以将该字符串连接到该可迭代对象,从而浪费内存和处理能力:
>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'
因此,我们看到我们必须添加一个额外的步骤来使用我们的列表方法,而不仅仅是使用内置的字符串方法:
>>> ' | '.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
对象上而不是在其他可迭代对象上还是有意义的。
-
在“-”中。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']}
两者都不好。
string.join(xs,delimit)表示字符串模块知道列表的存在,而列表列表却没有任何业务意义,因为字符串模块仅适用于字符串。
list.join(delimit)更好一点,因为我们习惯于将字符串作为基本类型(从语言上讲,它们是)。但是,这意味着需要动态调度连接,因为在a.split("\n")
python编译器,可能不知道a是什么,因此需要查找它(类似于vtable查找),如果您花很多时间这样做,这会很昂贵。次。
如果python运行时编译器知道列表是内置模块,则它可以跳过动态查找并将意图直接编码为字节码,否则,它需要动态地解析“ a”的“ join”,这可能是多层的每次调用的继承关系(因为两次调用之间,join的含义可能已更改,因为python是一种动态语言)。
可悲的是,这是抽象的最终缺陷。无论您选择哪种抽象,您的抽象都仅在您要解决的问题的背景下才有意义,因此,当您开始将它们胶合在一起时,您将永远无法获得与基础意识形态相一致的一致抽象而不将它们包装在与您的意识形态相符的视图中。知道了这一点,python的方法更灵活,因为它更便宜,您可以自己制作包装器或自己的预处理器,为此要花更多的钱才能使它看起来“更漂亮”。
-
声明您正在连接列表并转换为字符串,它是面向结果的。