需要对字符串join()方法进行一些澄清

时间:2019-01-15 16:38:37

标签: python

我正在从基础知识中学习python,在我的学习书中,我需要一些有关练习示例的帮助。原始任务是替换字符串“ Do n't panic!”。使用切片“点击”。

因此,这是我的原始代码,该代码无效:

phrase = "Don't panic!"
plist = list(phrase)
print(phrase)
print(plist)
new_phrase = ''.join([plist[1:3], plist[5], plist[4], plist[7], plist[6]])

出现int-r错误:

TypeError: sequence item 0: expected str instance, list found

这本书的正确答案是:

new_phrase = ''.join(plist[1:3])
new_phrase = new_phrase + ''.join([plist[5], plist[4], plist[7], plist[6]])

这就是我不明白的地方,我的错行和正确的行有什么区别?我看这两个序列都有字符串实例吗?

5 个答案:

答案 0 :(得分:4)

您正在通过混合切片和索引来混合另一个列表中的列表和字符串。切片会生成一个列表,为单个元素建立索引。

因此,工作代码仅将单个值放入列表中:

[plist[5], plist[4], plist[7], plist[6]]

而您的代码也使用切片:

[plist[1:3], plist[5], plist[4], plist[7], plist[6]]
#     ^^^^^

所以现在您的第一个元素是包含2个元素的列表。

str.join()只能连接字符串,因此所有 元素都必须是字符串,任何其他对象类型(例如列表)都将导致错误。

本书中的代码通过单独加入切片结果来解决此问题:

new_phrase = ''.join(plist[1:3])

这将获取切片列表,并将其直接传递给str.join() (而不是另一个列表的元素)。然后,本书中的代码将第二个str.join()调用的结果附加到下一行:

new_phrase = new_phrase + ''.join([plist[5], plist[4], plist[7], plist[6]])

现代Python(3.5或更高版本)确实具有将元素移到使用[...]语法创建的列表中的语法,方法是在项目之前添加{{1} };导致所有元素都被取出并放置在当前列表中。您也可以在这里使用它,将所有切片的字符串从切片中取出并进入新列表:

*

这取决于您使用的书的年龄,是否会引入这种语法。

在交互式解释器中查看Python表达式的组成元素发生了什么总是有帮助的。这是您的代码正在发生的事情:

''.join([*plist[1:3], plist[5], plist[4], plist[7], plist[6]])
#        ^ note the * here, meaning: take all elements from plist[1:3], not plist[1:3] itself.

看到那里的>>> phrase = "Don't panic!" >>> plist = list(phrase) >>> plist ['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c', '!'] >>> [plist[1:3], plist[5], plist[4], plist[7], plist[6]] [['o', 'n'], ' ', 't', 'a', 'p'] 元素了吗?这不是单个字符串值,因此['o', 'n']将不会接受它:

str.join()

但是如果您忽略了该部分,那么其余部分可以加入:

>>> ''.join([plist[1:3], plist[5], plist[4], plist[7], plist[6]])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected str instance, list found

如果我们使用>>> ''.join([plist[5], plist[4], plist[7], plist[6]]) ' tap' 语法,则会得到一个平面列表,而*接受:

''.join(...)

答案 1 :(得分:0)

您使用{p>构造plist

plist = list(phrase)

这意味着plistlist实例中的str,原始phrase字符串中的每个字符一个:

>>> plist
['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c', '!']

切片列表会产生另一个列表,因此plist[1:3]是一个列表:

>>> type(plist)
<class 'list'>
>>> type(plist[0])
<class 'str'>
>>> type(plist[0:1])
<class 'list'>

因此,您要传递给join的参数同时包含str对象和list对象(通过切片plist创建的列表):

>>> [plist[1:3], plist[5], plist[4], plist[7], plist[6]]
[['o', 'n'], ' ', 't', 'a', 'p']

>>> [type(x) for x in [plist[1:3], plist[5], plist[4], plist[7], plist[6]]]
[<class 'list'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>]

内部列表本身包含str对象并不重要,因为join不会检查该list对象。一旦它在可迭代的内部看到了不是str的可传递对象,它就会引发您看到的TypeError

答案 2 :(得分:0)

让我们首先讨论正确的答案。在这里,您将加入plist [1:3]并创建一个字符串对象,然后将其存储到new_phrase中。请记住,这现在是一个字符串。然后,您将此字符串添加到另一个字符串(由另一个连接函数创建),因此没有错误,因为您可以将字符串添加到字符串。

首先返回解决方案,plist [1:3]是一个列表而不是字符串,因此您不能在join函数中使用它,因为它需要一个列表而不是一个列表。

因此您可以将plist [1:3]设置为字符串

new_phrase = ''.join([''.join(plist[1:3]), plist[5], plist[4], plist[7], plist[6]])

等同于您所看到的正确代码。

答案 3 :(得分:0)

如此与您的原始实现接近。我不知道您的书是否已经引入了*(星号)符号,但是您可以使用*my_iter

以迭代方式传递每个项目

像这样:my_function(*my_iter)

或仅将其放入一个元组:(val_a, val_b, val_c, *val_iter)

快速示例:

my_list = [1,2,3,4]
my_tuple = (5,6,7,8)

combined_list = [*my_list, *my_tuple]
print(combined_list)
  

[1、2、3、4、5、6、7、8]

现在,回到您的问题:使用*表示法,我们可以轻松地解决星星问题,以便将您的字符串列表逐个元素地传递到''.join()中:< / p>

phrase = "Don't panic!"
plist = list(phrase)
new_phrase = ''.join([*plist[1:3], plist[5], plist[4], plist[7], plist[6]])
print(new_phrase)
  

点击

答案 4 :(得分:0)

正如Madhan指出的那样,您正在尝试使用列表作为第一个索引,而不是字符串。

来自pydocs:

  

str.join (可迭代)   返回一个字符串,该字符串是可迭代的字符串的串联。如果有可迭代的任何非字符串值(包括字节对象),则会引发TypeError。元素之间的分隔符是提供此方法的字符串。

因此,您只需要提供可迭代的字符串即可。 但是,如果看到代码,则使用的是多种类型的对象的列表。

第一个索引是一个列表,其他索引是字符串。

这是怎么回事:

your_param = [plist[1:3], plist[5], plist[4], plist[7], plist[6]]

type(your_param)
<class 'list'>

for param in your_param:
    type(param)

<class 'list'> # <--- HERE
<class 'str'>
<class 'str'>
<class 'str'>
<class 'str'>

如果您希望所有内容都在一行中,则可以执行以下操作:

your_param = [''.join(plist[1:3]), plist[5], plist[4], plist[7], plist[6]]

for param in your_param:
    type(param)

<class 'str'>
<class 'str'>
<class 'str'>
<class 'str'>
<class 'str'>