web-dev-qa-db-ja.com

python list内のオブジェクトのインスタンスを削除する

これはうまくいくはずですが、エラーが発生します。クラスnodeのオブジェクトを含むリストがあります。私は2つの異なるリストを持っています

  1. open_list
  2. node_list。(縦方向と順序は同じではありません)

_open_list_で特定のノードを見つけたら、それを_node_list_から削除する必要があります。リストに格納されているオブジェクトのアドレスがあることを知っています

だから私がやろうとすると

_removed = open_list.pop(min_index) 
node_list.remove(removed) 
_

それは私に言うエラーを与えます

_node_list.remove(removed)
ValueError: list.remove(x): x not in list
_

しかし、リストにはポインタのように機能するアドレスが含まれているだけですか?同じアドレスと一致する必要があります。 removedのアドレスを出力し、_node_list_全体(今のところ10項目のみ)を出力します:( node_listの最後の項目は削除されたアドレスと一致します:

_removed: <__main__.node instance at 0x0124A440>
node_list: [<__main__.node instance at 0x01246E90>, <__main__.node instance at 0x01246EE0>, <__main__.node instance at 0x0124A300>, <__main__.node instance at 0x0124A328>, <__main__.node instance at 0x0124A350>, <__main__.node instance at 0x0124A378>, <__main__.node instance at 0x0124A3A0>, <__main__.node instance at 0x0124A3C8>, <__main__.node instance at 0x0124A3F0>, <__main__.node instance at 0x0124A418>, <__main__.node instance at 0x0124A440>]
_

ありがとう

フォローアップQ

削除したいノードがnode_listに存在するかどうかを確認したいと思います。 http://docs.python.org/tutorial/datastructures.html でいくつかの簡単なリスト関数を調べたとき

要素がリストにない場合、list.index(x)remove.index(x)の両方でエラーが発生します。これにより、プログラムの実行が停止しました。これを回避するには、.remove()の前にこのステートメントを使用できますか:_node in node_list_ inは、要素がリストの一部であるかどうかを確認し、ブール値を返すと思います。感謝を再確認するだけです、

13
user1521385

これは、Nodeクラスの2つのインスタンスの機能を識別するものとして理解しているのは、pythonがそれを理解している方法ではないためです。

問題はここにあります。 python _5==5_、pythonはTrueを返します。これはpython = intsについて知っています。ただし、Nodeは定義したカスタムクラスであるため、2つのNodeオブジェクトがいつpythonあなたは(おそらく)そうではないので、pythonはデフォルトでメモリ内の場所を比較します。2つの別々のインスタンスが2つの異なるメモリ場所にあるため、pythonはFalseを返します。Javaに精通している場合、これは_==_と.equals(...)の違いのようなものです。

これを行うには、Nodeクラスに移動し、__eq__(self, other)メソッドを定義します。ここで、otherNodeの別のインスタンスであると想定されます。

たとえば、ノードにnameという属性があり、同じ名前の2つのノードが同じであると見なされる場合、___eq___は次のようになります。

_def __eq__(self, other):
    myName = self.name
    hisName = other.name
    if myName == hisName:
        return True
    else:
        return False
_

もちろん、同じ関数を書くためのよりエレガントな方法は次のとおりです。

_def __eq__(self, other):
    return self.name == other.name
_

これが行われると、エラーは消えるはずです

EDIT 1[〜#〜] dsm [〜#〜] のコメントへの応答

_class Node: pass
a = [Node(), Node()]
b = a[:]
b.remove(a.pop(0))
_

これは機能します。しかし、詳しく調べると、a [0]とb [0]が実際には同じオブジェクトであることが明らかになります。これは、id(a[0])を呼び出してid(b[[0])と比較し、それらが実際に同じであることを確認することで確認できます。

編集2:OPのフォローアップ質問への応答(編集として元の質問に追加)

はい、リストに存在しないオブジェクトはエラーを引き起こし、通常はプログラムの流れを停止します。これは、次の2つの方法のいずれかで解決できます。

_if x in my_list:
    my_list.remove(x)
_

OR

_try:
    my_list.remove(x)
except:
    pass
_

2番目の方法は、_my_list_からxを削除しようとし、その結果エラーが発生した場合、エラーを無視します

15
inspectorG4dget

フォローアップに応じて、yes inはリストのメンバーシップをチェックします。したがって、次のようになります。

if removed in node_list: node_list.remove(removed)

エラーは発生しません。または、エラーをトラップすることもできます。

try:
    node_list.remove(removed)
except ValueError:
    pass
3
Monkeyer

私が質問を正しく読んだ場合、メモリ位置を比較するPythonのデフォルトは、彼が探している動作ですが、取得されていません。カスタムクラスがNodeで定義されている実際の例を次に示します。これは、__eq__(self, other)が必要ないことを示しています。

class Node(object):
    pass

open_node_list = []
node_list = []

for i in range(10):
    a_node = Node()
    open_node_list.append(a_node)
    node_list.append(a_node)

removed = open_node_list.pop()
node_list.remove(removed)

open_node_listnode_listがどこで定義されているかを示していないため、わかりませんが、リスト自体が同じリストオブジェクトを参照していると思われます。その場合、open_node_listからのポップもnode_listからポップするため、removeを呼び出すとノードは存在しなくなります。 node_listopen_node_listが実際には同じリストであるため、一方を変更すると他方に影響する例を次に示します。

class Node(object):
  pass

open_node_list = []
node_list = open_node_list # <-- This is a reference, not a copy.

open_node_list.append(Node())
print(node_list)

リストをコピーする1つの方法は次のとおりです。

node_list = open_node_list[:]
2
Monkeyer