我正在从基础知识中学习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]])
这就是我不明白的地方,我的错行和正确的行有什么区别?我看这两个序列都有字符串实例吗?
答案 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)
这意味着plist
是list
实例中的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'>