python父子关系类

时间:2015-11-19 20:35:07

标签: python

我写了一节课,如下所示。我想将“ parent ”的属性添加到我的基类Node。我想知道是否有人可以告诉我如何正确地做到这一点。我已经获得了如何做到这一点的指导,但我并不完全确定如何以语法方式编写它。这是建议的方法......

  

一般来说,我会隐藏属性背后的父属性,所以当   它的集合,可以修改前一个父节点的子数组   如果你说n.parent = 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()

1 个答案:

答案 0 :(得分: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__方法,而不是最后一个。由于我在__init__上提供了Camera默认值,因此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__个参数移到前面,Camera可能会停止关注Node __init__中的更改;新Camera适用于原始Node或新Node(接受parent并指定self.parent)就好了,因为它不太紧密耦合到确切的参数排序。请注意,这确实意味着如果enabled未按位置传递,则所有参数必须通过关键字传递。

如果我犯了任何错误,请发表评论,但这应该接近正确。一般来说,我让Node类使用parent访问器来简化代码,方法是删除正确处理None的难度(None并非弱参照)。