Как ни глупо, как это могло бы звучать, попробовал все, и он не сработал и, наконец, перезапустил VS2012, чтобы увидеть, как он снова работает.
Как указал Мадхан в своем ответе, вы пытаетесь использовать список в качестве первого индекса, а не строку.
Взято из pydocs:
str.join (итерируемый) Возвращает строку, которая является конкатенацией строк в итерируемой. Ошибка TypeError будет возникать, если в итерируемых есть какие-либо нестроковые значения, включая байтовые объекты. Разделителем между элементами является строка, обеспечивающая этот метод.
blockquote>Таким образом, вам нужно предоставить только строки в вашей итерации. Но если вы видите свой код, вы используете список объектов нескольких типов.
Первый индекс представляет собой список, а другие индексы являются строками.
Вот что происходит:
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'>
Вы были , поэтому близки к вашей первоначальной реализации. Я не знаю, введена ли в вашей книге нотация * (звездочка), но вы можете передать каждый элемент в итерируемом с *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] [1112 ] blockquote>
Теперь вернемся к вашему вопросу: используя обозначение
*
, мы можем легко решить вашу проблему со звездочкой, чтобы ваш список строк передавался элемент за элементом в''.join()
:phrase = "Don't panic!" plist = list(phrase) new_phrase = ''.join([*plist[1:3], plist[5], plist[4], plist[7], plist[6]]) print(new_phrase)
на кране
blockquote>
Давайте сначала обсудим правильный ответ. Здесь вы присоединяетесь к plist [1: 3] и создаете строковый объект, затем сохраняете его в new_phrase. Имейте в виду, что теперь это строка. Затем вы добавляете эту строку в другую строку (которая создается другой функцией соединения), поэтому нет ошибки, поскольку вы можете добавить строку в строку.
Возвращаясь к вашему решению, прежде всего, plist [1: 3] - это список, а не строка, поэтому вы не можете использовать его внутри функции соединения, так как она ожидает список, а не список списка.
Таким образом, вы можете сделать plist [1: 3] для строки
new_phrase = ''.join([''.join(plist[1:3]), plist[5], plist[4], plist[7], plist[6]])
, что эквивалентно правильному коду, как вы можете видеть.
Вы создаете 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
объекты, так и [ 1112] объект (список, созданный срезанием 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
не проверяет этот [ 1116] объект. Как только он видит что-то внутри итерируемой вами пропущенной вещи, которая не является str
, он поднимает TypeError
, который вы видите.
Вы смешиваете списки и строки внутри другого списка, смешивая нарезку и индексацию. При нарезке создается список, индексирующий отдельный элемент.
Таким образом, рабочий код помещает только отдельных значений в список:
[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 или новее) имеет синтаксис для перемещения элементов из [ 1121] список в список, который вы создаете с помощью синтаксиса [...]
, добавляя элемент к *
; это приводит к тому, что все элементы вынимаются и помещаются в текущий список. Вы также можете использовать это здесь, чтобы вынуть все нарезанные строки из среза в новый список:
''.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.
Это будет зависеть от возраста книги, которую вы используете, будет ли она ввести этот синтаксис.
Всегда полезно посмотреть, что происходит с компонентными элементами выражений Python, в интерактивном интерпретаторе. Вот что происходит с вашим кодом:
>>> 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(...)
принимает, что:
>>> ''.join([*plist[1:3], plist[5], plist[4], plist[7], plist[6]])
'on tap'