17

これでうまくいくと思いますが、エラーが発生します。class のオブジェクトを含むリストがあります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():要素がリストの一部であり、bool を返すかどうかをチェックするnode in node_listと思います。in再確認するだけです、ありがとう

4

3 に答える 3

16

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

問題はここにあります。pythonに質問したとすると5==5、pythonはを返しTrueます。これは、Pythonがsについて知っているためintです。ただし、は定義したカスタムクラスであるため、2つのオブジェクトが同じであるNode場合はPythonに通知する必要があります。Nodeあなたは(おそらく)そうではないので、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

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

編集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)

また

try:
    my_list.remove(x)
except:
    pass

x2番目の方法は、からの削除を試みmy_list、その結果エラーが発生した場合、エラーを無視します

于 2012-07-12T16:57:13.327 に答える
4

あなたのフォローアップに応じて、 yesinはリストのメンバーシップをチェックします。

if removed in node_list: node_list.remove(removed)

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

try:
    node_list.remove(removed)
except ValueError:
    pass
于 2012-07-12T18:36:45.837 に答える
2

私が質問を正しく読んだ場合、メモリ位置を比較する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_listとがどこで定義されているかを示していないため、わかりませんがnode_list、リスト自体が同じリストオブジェクトを参照していると思われます。その場合、からのポップはからopen_node_listもポップするnode_listため、を呼び出すとノードは存在しなくなりますremove。これはnode_list、とopen_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[:]
于 2012-07-12T17:15:46.400 に答える