web-dev-qa-db-ja.com

str(list)はどのように機能しますか?

str(list)がコンソールにリストを表示する方法を返すのはなぜですか?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', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', "'", '"', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", '"', "'", ',', ' ', "'", ',', "'", ',', ' ', "'", ' ', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ',', ' ', '"', "'", '"', ',', ' ', "'", ']', "'", ']']
_
14
alvas

さて、あなたは全部で4つの質問があります。

1。 str(list)が、listがコンソールにどのように表示されるかを返すのはなぜですか? str(list)はどのように機能しますか?

str() および __str__() とは何ですか?

str()呼び出し可能オブジェクトは、オブジェクトのprintable形式のみを返します! docs から

str(object)は、常にeval()で受け入れ可能な文字列を返そうとするわけではありません。その目的は、印刷可能な文字列を返すことです。

オブジェクトの__str__()を呼び出すと、クラスのstr()関数が呼び出されます。再び documentation から

object.__str__(self)

str()組み込み関数およびprintステートメントによって呼び出され、オブジェクトの「非公式な」文字列表現を計算します。

list 呼び出し可能とは何ですか?

list()呼び出し可能オブジェクトは、引数として渡された反復可能オブジェクトからリストを作成します。再び docs から

Iterableのアイテムと同じ、同じ順序のアイテムであるlistを返します

したがって、str(list)は印刷可能なフォームを提供し、list(str(list))は文字列を反復処理します。つまり、list(str(list))は、渡された引数の印刷可能な形式の個々の文字のリストを提供します。

ネストされた呼び出し間の小さなウォークスルー、

与えられたリスト、_l = ['a','b'](あなたの質問のそれよりも小さな例を取ることについての謝罪)

str(l)を呼び出すと、リストlの印刷可能な形式、つまり_"['a','b']"_が返されます。

これで、_"['a','b']"_が文字列であり、実際にiterableであることがはっきりとわかります。これでlistを呼び出すと、つまりlist("['a','b']")になると、_['[', "'", 'a', "'", ',', "'", 'b', "'", ']']_のような奇妙なリストが表示されます。 なぜこれが起こるのですか?これは、文字列がその文字を反復処理するために発生します。ダミー文字列を使用してこれをテストできます。

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

したがって、文字列でlistを呼び出すと、文字のリストが表示されます。ここでも、str()list('dummy')を呼び出すと、元の文字列_'dummy'_が返されないため、再び joinを使用する必要があります。 !このため、同じ関数を呼び出すと[〜#〜](〜#〜]で元のオブジェクトに戻せません!

そのため、リストに対してstr()を呼び出すと、リストの組み込み__str__()メソッドが呼び出されますか?

答えはノーです!

リストでstr()を呼び出すと、内部で何が起こりますか?

リストオブジェクトでstr()を呼び出すと、必ず次の手順が実行されます。

  1. 各リスト要素のrepr()を呼び出します。
  2. リストの前に豪華な_[_を追加し、リストの最後に別の_]_を追加します。
  3. それらすべてをコンマで結合します。

cpython on github のリストオブジェクトのソースコードからわかるように、. より明確な hg.python でcpythonのソースコードを確認すると、次の3つのコメントが表示されます。 (その特定の code のリンクについては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()は、すべてのオブジェクトの文字列表現を出力します。再び documentation から

オブジェクトの印刷可能な表現を含む文字列を返します。

この文章にも注意してください!

多くのタイプの場合、この関数はeval()に渡されたときに同じ値のオブジェクトを生成する文字列を返そうとします。それ以外の場合、表現はタイプの名前を含む山括弧で囲まれた文字列です多くの場合、オブジェクトの名前とアドレスを含む追加情報と一緒にオブジェクトの。

そして、ここであなたの2番目の質問、

2。 list(str(list))str(list)を元のリストに戻さないのはなぜですか?

内部的には、str(list)は実際にはリストオブジェクトのrepr()表現を作成します。したがって、リストでstrを呼び出した後にリストを取得するには、実際にはeval呼び出しではなく list を実行する必要があります。

回避策

しかし、 evalevil であることは誰もが知っているので、回避策は何ですか?

1. _literal_eval_ を使用する

最初の回避策は _ast.literal_eval_ を使用することです。これで3番目の質問に進みます。

3。 literal_eval()eval()と同じですか? eval()を使用しても安全ですか?

ast.literal_eval() 安全です 違うeval()関数。ドキュメント自体は安全だと述べています-

安全に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]_のように本質的に異種である場合、分割リストをループして要素タイプを検出し、それを変換して、変換された要素を最終リストに追加する必要があります。

これが失敗するもう1つの場所は、文字列自体に引用文字が含まれている場合です。 nneonneo で言及されているように comment

_str.split_ソリューションは非常に壊れやすく、入力にたとえば_", "_を含む文字列、またはタプル、または他のリスト、... _ast.literal_eval_を使用する方がはるかに優れています。

そして最後の質問ですが

4。 str(list(str(list))))を何度も実行すると、コードは壊れますか?

あんまり。 liststrを作成し、その印刷可能なバージョンを再び取得するたびに、出力はますます長くなります。制限は、物理マシンの制限のみです。 (各ステップで文字列の長さが5倍されるとすぐに到達します。)

62
Bhargav Rao

あなたは、リストから文字列を作成することが往復可能であるという期待を持っているように見えます。それは意図されていません。リストはエンドユーザーが提示できるオブジェクトではなく、repr(listobject)と同じ出力が得られます。開発者の消費に関するデバッグ情報のみ。

list()呼び出し可能オブジェクトは、任意の反復可能なオブジェクトから新しいリストオブジェクトを作成します。 Python文字列は反復可能であり、個別の文字を生成する場合、list(stringobject)は常に個別の文字を含むリストを生成します。

そのため、list()は、文字列引数をPython構文として解釈しようとはしません。元のリストにPythonリテラル表記。例を見てみましょう:

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

特にPythonインタープリターでこのような関数が定義されていないところでこれを実行する場合、そのデバッグ文字列出力を元のリストに戻すことはできません。

7
Martijn Pieters

python=のstr()関数は、値を文字列に変換するために使用されます。str()listは、リストの文字列表現(角括弧とすべて)を作成することです。

list(str(list))に関しては、pythonに元のリストを文字列に変換するように指示しているだけで、その文字列を分割してリストに入れ、インデックスは1文字であるため、liststrの呼び出しを必要なだけネストすることができます(コンピュータに十分なメモリがある場合)。

3
NendoTaka