2016-11-13 2 views
-1

私はPythonでグラフノードクラスを作成しました。
各ノードには、単一の親、複数の子およびプロパティがあります。
実装は以下のようにすべきである:このコードでpythonオブジェクトはinitialzeでプロパティを持っています

# graph_test.py 
class Node(object): 
    def __init__(self, name, prop={}): 
     self.name = name 
     self.properties = prop 
     self.parent = None 
     self.children = [] 
     print "New node:", self.name, self.properties 
    def add_prop(self, k, v): 
     self.properties.update({k:v}) 
     print "added prop:", k, v 
    def add_child(self, n): 
     self.children.append(n) 
     n.parent = self 

class Foo(object): 
    def __init__(self, n): 
     self.node_num = n 
     self.root_node = None 
     self.current_node = None 
    def bas(self): 
     n = Node("root") 
     n.add_prop("this_prop_is", "set_only_root_node") 
     self.root_node = n 
     return self.root_node 
    def bar(self): 
     self.current_node = self.bas() 
     for i in range(self.node_num): 
      n = Node(str(i)) 
      self.current_node.add_child(n) 
      self.current_node = n 

if __name__ == '__main__': 
    f = Foo(5) 
    f.bar() 

、唯一のルートノードは、そのキー「this_prop_is」である特性を有していることが予想されます。
はしかし、実行結果は以下のようなものです:

$ python ./graph_test.py 
New node: root {} 
added prop: this_prop_is set_only_root_node 
New node: 0 {'this_prop_is': 'set_only_root_node'} 
New node: 1 {'this_prop_is': 'set_only_root_node'} 
New node: 2 {'this_prop_is': 'set_only_root_node'} 
New node: 3 {'this_prop_is': 'set_only_root_node'} 
New node: 4 {'this_prop_is': 'set_only_root_node'} 

すべてのノードでも、私が唯一のノード「ルート」に追加し、同じキーを持っています。

私はpython 2.7.6を使用します。

私の質問は以下のとおりです。

  • これはバグですか?
  • これはバグではない場合、なぜこれが発生しますか?
  • この問題を解決するにはどうすればよいですか?

答えて

2

これはバグではありません。問題はpropのデフォルト値です。空の辞書として設定します。ただし、この空の辞書はself.properties = propで参照してコピーされ、変更されたときに次回新しいNodeが作成されると、変更された辞書がデフォルト値として使用されます。 self.properties = prop or {}

# graph_test.py 
class Node(object): 
    def __init__(self, name, prop=None): 
     self.name = name 
     self.properties = prop or {} 
     self.parent = None 
     self.children = [] 
     print "New node:", self.name, self.properties 
    def add_prop(self, k, v): 
     self.properties.update({k:v}) 
     print "added prop:", k, v 
    def add_child(self, n): 
     self.children.append(n) 
     n.parent = self 

class Foo(object): 
    def __init__(self, n): 
     self.node_num = n 
     self.root_node = None 
     self.current_node = None 
    def bas(self): 
     n = Node("root") 
     n.add_prop("this_prop_is", "set_only_root_node") 
     self.root_node = n 
     return self.root_node 
    def bar(self): 
     self.current_node = self.bas() 
     for i in range(self.node_num): 
      n = Node(str(i)) 
      self.current_node.add_child(n) 
      self.current_node = n 

if __name__ == '__main__': 
    f = Foo(5) 
    f.bar() 
+0

ありがとうございました。 C++では、デフォルトの引数はすべての関数呼び出しで評価されるため、非常に混乱します... – furushchev

1

これは、変更可能なデフォルト値がNode.__init__であるためです。 Pythonでは、関数の作成時にデフォルト値が決定され、常に同じインスタンスが使用されます。したがって、新しいNodeを作成し、それに明示的なprop引数を与えないたびに、同じ辞書を使用します。

これは、デフォルト値としてNoneを使用し、引数がself.properties = prop or {}など、引数がNoneの場合、関数内で新しい辞書を作成することで解決されることがよくあります。 (辞書を空にすると新しい辞書も使用されますが、これはではありません)

0

props=Noneに変更props={}self.properties = propこれは変更可能なデフォルトの動作によるものです:プロパティを割り当てるときに、この問題を解決するには

は、デフォルト値としてNoneを入れていないし、なしをチェックPythonの引数この記事を読むには、ここをクリックしてください:http://effbot.org/zone/default-values.htm

関連する問題