我写了一节课,如下所示。我想将“ 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()
答案 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
并非弱参照)。