2016-11-13 1 views
-1

파이썬에서 그래프 노드 클래스를 만들었습니다.
각 노드에는 단일 상위, 여러 하위 및 속성이 있습니다.
구현은 다음과 같이해야합니다 :파이썬 객체는 초기화에 대한 속성을 가지고 있습니다.

이 코드에서
# 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__입니다. 파이썬에서는 함수가 생성 될 때 기본값이 결정되며, 동일한 인스턴스가 항상 사용됩니다. 따라서 새 Node을 만들 때마다 명시적인 prop 인수를주지 않을 때마다 과 동일한 사전을 사용합니다.

이것은 self.properties = prop or {}과 같이 인수가 None 인 경우 함수 내에서 항상 새로운 사전을 만들고 기본값으로 None을 사용하여 해결됩니다. (빈 사전을 주면 새 사전도 사용되지만, 은 일반적으로이 아닙니다.

0

props=None로 변경 props={}self.properties = prop이 변경 가능한 기본의 행동 때문이다 : 속성을 할당 할 때이 문제를 해결하려면

는 기본 값으로 없음을 넣어하지 않으며 없음을 확인 파이썬의 인수. 여기에 대한 좋은 자료가 있습니다. http://effbot.org/zone/default-values.htm

관련 문제