str(list) 是如何工作的?
How does str(list) work?
为什么 str(list)
returns 我们如何在控制台上看到列表? str(list)
是如何工作的? (对 str(list)
的 CPython 代码的任何引用)?
>>> 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', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ']']
你一共有4个问题,我们一一解答。
1. Why does str(list)
returns how we see list
on the console? How does str(list)
work?
什么是str()
and __str__()
?
str()
可调用对象仅是 return 可打印 形式的对象!来自 docs
str(object)
does not always attempt to return a string that is
acceptable to eval()
; its goal is to return a printable string.
只要您在对象上调用 str()
,就会调用 class 中的 __str__()
函数。再次来自 documentation
object.__str__(self)
Called by the str()
built-in function and by the print
statement to compute the “informal” string representation of an object.
什么是 list
可调用项?
list()
可调用函数是从作为参数传递的可迭代对象创建一个列表。再次来自 docs
Return a list
whose items are the same and in the same order as
iterable‘s items
因此,str(list)
为您提供了一个可打印的表单,而 list(str(list))
将遍历该字符串。即 list(str(list))
将为您提供所传递参数的可打印形式的单个字符列表。
嵌套调用之间的小走查,
给定列表,l = ['a','b']
(很抱歉举了一个比你问题中的小的例子)。
当您调用 str(l)
时,它 return 是列表 l
的可打印形式,即 "['a','b']"
。
现在可以清楚地看到"['a','b']"
是一个字符串,确实是一个iterable。现在当你调用 list
时,即 list("['a','b']")
你会得到一个奇怪的列表,比如 ['[', "'", 'a', "'", ',', "'", 'b', "'", ']']
。 为什么会这样?这是因为字符串遍历了它的字符,你可以使用虚拟字符串来测试,
>>> 'dummy'
'dummy'
>>> list('dummy')
['d', 'u', 'm', 'm', 'y']
因此,当您在字符串上调用 list
时,您会得到一个字符列表。请再次注意,当您在 list('dummy')
上调用 str()
时,您将不会取回原始字符串 'dummy'
,因此您将不得不再次使用 join
!因此,调用相同的函数 不会 让您找回原来的对象!
那么,在列表上调用 str()
会调用列表的内置 __str__()
方法吗?
答案是否定的!
当您在列表中调用 str()
时内部会发生什么?
每当您在列表对象上调用 str()
时,遵循的步骤是
- 调用每个列表元素的
repr()
。
- 在列表的前面添加一个花哨的
[
,在列表的末尾添加另一个 ]
。
- 用逗号连接所有这些。
从cpython on github. Going through the source code of cpython in hg.python, which is more clear, you can see the following three comments. (Thanks to Ashwini for the link on that particular )
中list对象的源码可以看出
/* 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()
打印所有对象的字符串表示形式。再次来自 documentation
Return a string containing a printable representation of an object.
还要注意这句话!
For many types, this function makes an attempt to return a string
that would yield an object with the same value when passed to eval()
,
otherwise the representation is a string enclosed in angle brackets
that contains the name of the type of the object together with
additional information often including the name and address of the
object.
现在你的第二个问题,
2. Why doesn't list(str(list))
turns the str(list)
back to the original list?
在内部,str(list)
实际上创建了列表对象的 repr()
表示。因此,要在列表上调用 str
后取回列表,您实际上需要对其执行 eval
而不是 list
调用。
解决方法
但我们都知道 eval
is evil,那么 is/are 解决方法是什么?
1。使用 literal_eval
第一个解决方法是使用 ast.literal_eval
。这就引出了你的第三个问题,
3. Is literal_eval()
the same as eval()
? Is eval()
safe to use?
ast.literal_eval()
is safe unlike eval()
函数。文档本身提到它是安全的——
Safely evaluate an expression node or a string containing a Python literal or container display
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 in a
所述
The str.split
solution is very fragile and will break if the input contains e.g. strings that contain ", "
, or tuples, or other lists, ... It is much better to use ast.literal_eval
because that will deal with all the subtleties of the syntax.
最后一个问题,
4. Does the code break if you do str(list(str(list))))
again and again?
不是真的。每次您创建 str
的 list
然后再次获取它的可打印版本时,输出会越来越长。该限制只是您的物理机器的限制。 (随着字符串长度的每一步乘以 5,很快就会达到。)
您似乎期望从列表创建字符串是可往返的。这不是故意的;列表不是最终用户可呈现的对象,您得到与 repr(listobject)
相同的输出;仅供开发人员使用的调试信息。
list()
可调用函数从任意可迭代对象创建一个新的列表对象; Python 字符串可迭代生成单个字符,list(stringobject)
始终生成包含单个字符的列表。
因此,list()
永远不会尝试将字符串参数解释为 Python 语法;如果原始列表包含没有 Python 文字符号的对象,那么这样做甚至不会起作用。举个例子:
>>> def foo(): return 'bar'
...
>>> alist = [foo]
>>> alist
[<function foo at 0x106c748c0>]
您不能获取调试字符串输出并将其转换回原始列表,尤其是如果您 运行 在 Python 解释器中使用它甚至没有定义这样的函数。
python中的str()
函数用于将一个值转为字符串。 str()
对 list
的作用的简单答案是它创建列表的字符串表示形式(方括号和所有)。
至于 list(str(list))
,您所做的只是告诉 python 将原始列表转换为字符串,然后拆分该字符串并将其放入列表中,以便每个索引都有一个字符。因此,您可以根据需要嵌套 list
和 str
调用(假设您的计算机有足够的内存)。
为什么 str(list)
returns 我们如何在控制台上看到列表? str(list)
是如何工作的? (对 str(list)
的 CPython 代码的任何引用)?
>>> 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', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ']']
你一共有4个问题,我们一一解答。
1. Why does
str(list)
returns how we seelist
on the console? How doesstr(list)
work?
什么是str()
and __str__()
?
str()
可调用对象仅是 return 可打印 形式的对象!来自 docs
str(object)
does not always attempt to return a string that is acceptable toeval()
; its goal is to return a printable string.
只要您在对象上调用 str()
,就会调用 class 中的 __str__()
函数。再次来自 documentation
object.__str__(self)
Called by the
str()
built-in function and by the
什么是 list
可调用项?
list()
可调用函数是从作为参数传递的可迭代对象创建一个列表。再次来自 docs
Return a
list
whose items are the same and in the same order as iterable‘s items
因此,str(list)
为您提供了一个可打印的表单,而 list(str(list))
将遍历该字符串。即 list(str(list))
将为您提供所传递参数的可打印形式的单个字符列表。
嵌套调用之间的小走查,
给定列表,l = ['a','b']
(很抱歉举了一个比你问题中的小的例子)。
当您调用 str(l)
时,它 return 是列表 l
的可打印形式,即 "['a','b']"
。
现在可以清楚地看到"['a','b']"
是一个字符串,确实是一个iterable。现在当你调用 list
时,即 list("['a','b']")
你会得到一个奇怪的列表,比如 ['[', "'", 'a', "'", ',', "'", 'b', "'", ']']
。 为什么会这样?这是因为字符串遍历了它的字符,你可以使用虚拟字符串来测试,
>>> 'dummy'
'dummy'
>>> list('dummy')
['d', 'u', 'm', 'm', 'y']
因此,当您在字符串上调用 list
时,您会得到一个字符列表。请再次注意,当您在 list('dummy')
上调用 str()
时,您将不会取回原始字符串 'dummy'
,因此您将不得不再次使用 join
!因此,调用相同的函数 不会 让您找回原来的对象!
那么,在列表上调用 str()
会调用列表的内置 __str__()
方法吗?
答案是否定的!
当您在列表中调用 str()
时内部会发生什么?
每当您在列表对象上调用 str()
时,遵循的步骤是
- 调用每个列表元素的
repr()
。 - 在列表的前面添加一个花哨的
[
,在列表的末尾添加另一个]
。 - 用逗号连接所有这些。
从cpython on github. Going through the source code of cpython in hg.python, which is more clear, you can see the following three comments. (Thanks to Ashwini for the link on that particular
/* 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()
打印所有对象的字符串表示形式。再次来自 documentation
Return a string containing a printable representation of an object.
还要注意这句话!
For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to
eval()
, otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object.
现在你的第二个问题,
2. Why doesn't
list(str(list))
turns thestr(list)
back to the original list?
在内部,str(list)
实际上创建了列表对象的 repr()
表示。因此,要在列表上调用 str
后取回列表,您实际上需要对其执行 eval
而不是 list
调用。
解决方法
但我们都知道 eval
is evil,那么 is/are 解决方法是什么?
1。使用 literal_eval
第一个解决方法是使用 ast.literal_eval
。这就引出了你的第三个问题,
3. Is
literal_eval()
the same aseval()
? Iseval()
safe to use?
ast.literal_eval()
is safe unlike eval()
函数。文档本身提到它是安全的——
Safely evaluate an expression node or a string containing a Python literal or container display
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 in a
The
str.split
solution is very fragile and will break if the input contains e.g. strings that contain", "
, or tuples, or other lists, ... It is much better to useast.literal_eval
because that will deal with all the subtleties of the syntax.
最后一个问题,
4. Does the code break if you do
str(list(str(list))))
again and again?
不是真的。每次您创建 str
的 list
然后再次获取它的可打印版本时,输出会越来越长。该限制只是您的物理机器的限制。 (随着字符串长度的每一步乘以 5,很快就会达到。)
您似乎期望从列表创建字符串是可往返的。这不是故意的;列表不是最终用户可呈现的对象,您得到与 repr(listobject)
相同的输出;仅供开发人员使用的调试信息。
list()
可调用函数从任意可迭代对象创建一个新的列表对象; Python 字符串可迭代生成单个字符,list(stringobject)
始终生成包含单个字符的列表。
因此,list()
永远不会尝试将字符串参数解释为 Python 语法;如果原始列表包含没有 Python 文字符号的对象,那么这样做甚至不会起作用。举个例子:
>>> def foo(): return 'bar'
...
>>> alist = [foo]
>>> alist
[<function foo at 0x106c748c0>]
您不能获取调试字符串输出并将其转换回原始列表,尤其是如果您 运行 在 Python 解释器中使用它甚至没有定义这样的函数。
python中的str()
函数用于将一个值转为字符串。 str()
对 list
的作用的简单答案是它创建列表的字符串表示形式(方括号和所有)。
至于 list(str(list))
,您所做的只是告诉 python 将原始列表转换为字符串,然后拆分该字符串并将其放入列表中,以便每个索引都有一个字符。因此,您可以根据需要嵌套 list
和 str
调用(假设您的计算机有足够的内存)。