Подтвердить что ты не робот

Как работает str (список)?

Почему str(list) возвращает то, как мы видим список на консоли? Как работает str(list)? (любая ссылка на код CPython для str(list))?

>>> x = ['abc', 'def', 'ghi']
>>> str(x)
"['abc', 'def', 'ghi']"

Чтобы вернуть исходный список из str(list), я должен:

>>> from ast import literal_eval
>>> x = ['abc', 'def', 'ghi']
>>> str(x)
"['abc', 'def', 'ghi']"
>>> list(str(x))
['[', "'", 'a', 'b', 'c', "'", ',', ' ', "'", 'd', 'e', 'f', "'", ',', ' ', "'", 'g', 'h', 'i', "'", ']']
>>> literal_eval(str(x))
['abc', 'def', 'ghi']

Почему list(str(list)) не возвращает str(list) в исходный список?

Или я мог бы использовать:

>>> eval(str(x))
['abc', 'def', 'ghi']

Является ли literal_eval тем же, что и eval? Безопасен ли eval?

Сколько раз я могу сделать следующее? Прерывает ли код, если он продолжает делать str(list(str(list))))?, например.

>>> x = 'abc'
>>> list(x)
['a', 'b', 'c']
>>> str(list(x))
"['a', 'b', 'c']"
>>> list(str(list(x)))
['[', "'", 'a', "'", ',', ' ', "'", 'b', "'", ',', ' ', "'", 'c', "'", ']']
>>> str(list(str(list(x))))
'[\'[\', "\'", \'a\', "\'", \',\', \' \', "\'", \'b\', "\'", \',\', \' \', "\'", \'c\', "\'", \']\']'
>>> list(str(list(str(list(x)))))
['[', "'", '[', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'a', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'b', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'c', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ']']
>>> str(list(str(list(str(list(x))))))
'[\'[\', "\'", \'[\', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \'a\', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \',\', "\'", \',\', \' \', "\'", \' \', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \'b\', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \',\', "\'", \',\', \' \', "\'", \' \', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \'c\', "\'", \',\', \' \', \'"\', "\'", \'"\', \',\', \' \', "\'", \']\', "\'", \']\']'
>>> list(str(list(str(list(str(list(x)))))))
['[', "'", '[', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '[', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'a', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'b', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", 'c', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ']']
4b9b3361

Ответ 1

Хорошо, у вас есть в общей сложности 4 вопроса, давайте пойдем один за другим.

1. Почему str(list) возвращает, как мы видим list на консоли? Как работает str(list)?

Что такое str() и __str__()

str(), подлежащий вызову, заключается в том, чтобы вернуть только печатную форму объекта! Из docs

str(object) не всегда пытается вернуть строку, которая приемлемо для eval(); его цель - вернуть печатную строку.

Функция __str__() в классе вызывается всякий раз, когда вы вызываете str() на объект. Опять из документация

object.__str__(self)

Вызывается встроенной функцией str() и оператором print для вычисления "неформального" строкового представления объекта.

Что такое list вызываемый?

list() вызываемый - это создать список из итеративного переданного в качестве аргумента. Снова из docs

Верните a list, элементы которого совпадают и находятся в том же порядке, что и пункты iterable

Таким образом, str(list) предоставляет вам печатную форму и list(str(list)) будет перебирать строку. Это list(str(list)) даст вам список отдельных символов печатаемой формы переданного аргумента.

Небольшое прохождение между вложенными вызовами,

Данный список, l = ['a','b'] (Извинения за использование меньшего примера, чем в вашем вопросе).

Когда вы вызываете str(l), он возвращает печатную форму списка l, то есть "['a','b']".

Теперь вы можете ясно видеть, что "['a','b']" является строкой и действительно является итерируемой. Теперь, когда вы вызываете list на этом i.e. list("['a','b']"), вы получаете странный список, например ['[', "'", 'a', "'", ',', "'", 'b', "'", ']']. Почему это происходит? Это происходит потому, что строка итерации над ее символами, вы можете проверить это, используя фиктивную строку,

>>> 'dummy'
'dummy'
>>> list('dummy')
['d', 'u', 'm', 'm', 'y']

Таким образом, когда вы вызываете list в строке, вы получаете список символов. Обратите внимание, что снова здесь, когда вы вызываете str() на list('dummy'), вы не вернете исходную строку 'dummy', так что вам снова придется использовать join! Таким образом, для вызова той же функции будет НЕ вернуть исходный объект!

Итак, вызов str() по списку вызывает встроенный метод __str__() списка?

Ответ НЕТ!

Что происходит внутри, когда вы вызываете str() в списке?

Всякий раз, когда вы вызываете str() в объекте списка, следующие шаги:

  • Вызвать repr() каждого из элементов списка.
  • Добавьте fancy [ спереди и еще один ] в конец списка.
  • Соедините их с запятой.

Как вы можете видеть из исходного кода объекта списка в cpython on github. Переход через источник код cpython в hg.python, что более понятно, вы можете увидеть следующие три комментария. (Спасибо Ashwini за ссылку на этот код)

/* Do repr() on each element.  Note that this may mutate the list,
   so must refetch the list size on each iteration. */ line (382)

/* Add "[]" decorations to the first and last items. */ line (398)

/* Paste them all together with ", " between. */ line (418)

Они соответствуют точкам, упомянутым выше.

Теперь что такое repr()?

repr() выводит строковое представление всех объектов. Снова из документация

Возвращает строку, содержащую печатаемое представление объекта.

а также обратите внимание на это предложение!

Для многих типов эта функция пытается вернуть строку что даст объект с тем же значением, если он передан на eval(), иначе представление представляет собой строку, заключенную в угловые скобки который содержит имя типа объекта вместе с Дополнительная информация часто включает имя и адрес объект.

И теперь ваш второй вопрос здесь,

2. Почему list(str(list)) не возвращает str(list) в исходный список?

Внутри str(list) фактически создает представление repr() объекта списка. Поэтому, чтобы вернуть список после вызова str в списке, вам действительно нужно сделать eval, а не list вызов.

Обходные

Но мы все знаем, что eval является злым, так что это/является обходным путем (-ами)?

1. Используя literal_eval

Первым обходом будет использование ast.literal_eval. Это подводит нас к вашему третьему вопросу,

3. Является ли literal_eval() тем же, что и eval()? Безопасен ли eval()?

ast.literal_eval() является безопасным в отличие от eval() функция. В самих документах говорится, что это безопасно -

Безопасно оценить выражение node или строку, содержащую литеральный или контейнерный дисплей Python

2. Использование строковых функций и встроенных функций

Еще одно решение может быть выполнено с помощью str.split()

>>> x = ['abc', 'def', 'ghi']
>>> a = str(x)
>>> a[2:-2].split("', '")
['abc', 'def', 'ghi']

Это простой способ сделать это для списка строк. Для списка целых чисел вам понадобится map.

>>> x = [1,2,3]
>>> a =str(x)
>>> list(map(int,a[1:-1].split(', '))) # No need for list call in Py2
[1, 2, 3]

Таким образом, в отличие от literal_eval, это простые хаки, учитывая, что вы знаете элементы списка. Если они являются гетерогенными по своему характеру, например [1, "a", True], вам придется перебирать список разделов и обнаруживать тип элемента, а затем преобразовывать его и добавлять преобразованный элемент в конечный список.

Другое место, где это не удается, - это когда сама строка содержит символы кавычек. Как упоминалось nneonneo в comment

Решение str.split очень хрупкое и будет ломаться, если вход содержит, например. строки, содержащие ", ", или кортежи, или другие списки... Лучше использовать ast.literal_eval, потому что это будет касаться всех тонкостей синтаксиса.

И для вашего последнего вопроса,

4. Разрыв кода, если вы делаете str(list(str(list)))) снова и снова?

Не совсем. Выход будет увеличиваться дольше и дольше, как каждый раз, когда вы создаете list для str, а затем снова получаете версию для печати. Ограничение ограничено только вашим физическим ограничением. (который скоро будет достигнут как каждый шаг, длина строки будет умножена на 5.)

Ответ 2

У вас появляется ожидание того, что создание строки из списка является круглым. Это не должно быть; списки не являются представляемыми конечным пользователем объектами, и вы получаете тот же результат, что и repr(listobject); отладочная информация только для потребления разработчиками.

Вызываемый list() создает новый объект списка из любого произвольного итерируемого объекта; Строки Python повторяются, производя отдельные символы, когда вы это делаете, list(stringobject) всегда создает список с отдельными символами.

Таким образом, list() никогда не попытается интерпретировать строковый аргумент как синтаксис Python; и это не будет даже работать, если исходный список содержит объекты без литеральной записи Python. Возьмем, к примеру:

>>> def foo(): return 'bar'
... 
>>> alist = [foo]
>>> alist
[<function foo at 0x106c748c0>]

Вы не можете взять этот вывод строки debug и повернуть его обратно в исходный список, особенно если вы запустите его в интерпретаторе Python, где даже не определена такая функция.

Ответ 3

Функция str() в python используется для преобразования значения в строку. Простой ответ на то, что делает str() для list, заключается в том, что он создает строковое представление списка (квадратные скобки и все).

Что касается list(str(list)), все, что вы делаете, это python, чтобы преобразовать исходный список в строку, тогда вы разбиваете эту строку и помещаете ее в список, чтобы каждый индекс имел один символ. Таким образом, вы можете вставлять list и str вызовы столько раз, сколько хотите (при условии, что на вашем компьютере достаточно памяти).