2015-11-19 114 views
2

我寫了一個類,如下所示。我想將'父項'的屬性添加到我的基類節點。我想知道如果有人能告訴我如何正確地做到這一點。我已經得到了如何做到這一點的指導,但我並不完全確定如何寫出語法。這是建議的方式來做到這一點...python父母子女關係課

通常我會隱藏如此 其集時,前面的家長的孩子陣列可以被修改,從而 如果你說N A特性背後的父屬性。父= X,它實際上移除節點n從它的父 和設置父值

class Node(object): 
    def __init__(self, name, attributes, children): 
     self.name = name 
     self.attributes = attributes if attributes is not None else {} 
     self.children = children if children is not None else [] 


class Camera(Node): 
    def __init__(self, name="", attributes=None, children=None, enabled=True): 
     super(Camera, self).__init__(name=name, attributes=attributes, children=children) 
     self.enabled = enabled 

更新

import weakref 

class Node(object): 
    _parent = None 

    def __init__(self, name, attributes, children, parent): 
     self.name = name 
     self.attributes = attributes if attributes is not None else {} 
     self.children = children if children is not None else [] 
     self.parent = parent 

     for child in children: 
      child.parent = self 

    @property 
    def parent(self): 
     return self._parent() if self._parent is not None else None 

    @parent.setter 
    def parent(self, newparent): 
     oldparent = self.parent 

     if newparent is oldparent: 
      return 
     if oldparent is not None: 
      oldparent.children.remove(self) 
     if self not in newparent.children: 
      newparent.children.append(self) 
     self._parent = weakref.ref(newparent) if newparent is not None else None 


class Camera(Node): 
    def __init__(self, name="", attributes=None, children=None, enabled=True, parent=None): 
     super(Camera, self).__init__(name=name, attributes=attributes, children=children, parent=parent) 
     self.enabled = enabled 




Camera() 
+0

附加說明:最好使用'weakref.ref'或'weakref.proxy'來存儲'_parent'屬性(我們假設'parent'是一個'property',所以在這種情況下慣例通常是用下劃線前綴命名「真實」屬性)。否則,你的樹,保證創建參考週期,因此他們不會被確定性清理(如果有的螺母禁用循環GC,或者在週期的任何對象都有一個'__del__'終結了'class'內存泄漏, [在Python 3.3及更早版本中,cyclic gc無法處理它](https://docs.python.org/3/whatsnew/3.4.html#whatsnew-pep-442))。 – ShadowRanger

+0

什麼即時通訊希望做父母的相機到另一臺相機 – JokerMartini

回答

1

實施例的代碼,結合weakref避免參考週期可以延遲清除(或防止它完全在某些情況下,particularly on Python 3.3 and earlier):

import weakref 

class Node: 
# If this is Python 2, you need to explicitly inherit from object to 
# be a new-style class with descriptor support (which allows properties), so 
# the class line would be: 
# class Node(object): 
# On Py3, it's implicit and can be omitted 

    # Ensure attribute readable so getter/setter don't need to use has/getattr 
    # Will be allocated per-instance when self.parent is assigned in __init__ 
    # So on Py3.3+, it will still get the compact key-sharing dicts for attributes 
    _parent = None 

    # Adding defaults for all values matching Camera for simplicity 
    def __init__(self, name='', attributes=None, children=None, parent=None): 
     self.name = name 
     self.attributes = attributes if attributes is not None else {} 
     self.children = children if children is not None else [] 
     self.parent = parent 
     for child in children: 
      child.parent = self 

    @property 
    def parent(self): 
     return self._parent() if self._parent is not None else None 

    @parent.setter 
    def parent(self, newparent): 
     oldparent = self.parent 
     # If setting to existing parent, then no-op 
     # Remove this check and early-out if you want to be able to move 
     # a node to the end of its parent's children by reassigning the same parent 
     if newparent is oldparent: 
      return 
     if oldparent is not None: 
      oldparent.children.remove(self) 
     if self not in newparent.children: 
      newparent.children.append(self) 
     self._parent = weakref.ref(newparent) if newparent is not None else None 

通常,爲了避免與改變父類的原型的問題,我把附加首先參數到子類__init__方法,而不是最後一個。因爲我給了上Camera__init__違約,這使得Camera很簡單:

class Camera(Node): 
    def __init__(self, enabled=True, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
     # On Py2, super isn't magic, so you need to be explicit unlike Py3: 
     # super(Camera, self).__init__(*args, **kwargs) 
     self.enabled = enabled 

正如你所看到的,由Camera獨特__init__ PARAM移動到前,Camera可以停止關注在Node__init__變化;新Camera作品與原Node或新Node(接受parent和分配self.parent)就好了,因爲它不太緊密耦合的確切參數排序。請注意,這意味着如果enabled未通過位置傳遞,則所有參數都必須通過關鍵字傳遞。

請評論,如果我犯任何錯誤,但應該是接近正確。一般來說,我有Node類使用parent訪問者通過正確處理NoneNone不是弱引用)來消除難度來簡化代碼。

+0

我已經提前和更新我的代碼上面,我粘貼舊代碼。我使用的是像你所提到的新的「超級」的東西。對困惑感到抱歉。讓我知道,如果這改變了你的代碼 – JokerMartini

+0

的例子中的任何東西,你的例子是否展示了我以黃色突出顯示的最初問題中提到的所有內容? – JokerMartini

+0

@JokerMartini:我最初忘了將它添加到新「父」的「子」中,但現在在那裏。大部分魔法都在'@ parent.setter'方法中;每當你分配'n。parent = x',它調用'x'作爲新父項的方法,它將爲你執行'weakref'魔術,從其父''(如果有的話)'children'移除'n',並且將它添加到新的「父」(如果不是「無」)子節點。我還爲'setter'早期增加了一個優化/正確性,所以一遍又一遍的重新分配同一個'parent'並不會做不必要的工作。 – ShadowRanger