继承Python中的实例

11 python inheritance overloading instance

在Python中,我想直接从Parent类的实例构造一个Child类的实例.例如:

A = Parent(x, y, z)
B = Child(A)
Run Code Online (Sandbox Code Playgroud)

这是我认为可行的黑客行为:

class Parent(object):

    def __init__(self, x, y, z):
        print "INITILIZING PARENT"
        self.x = x
        self.y = y
        self.z = z

class Child(Parent):

    def __new__(cls, *args, **kwds):
        print "NEW'ING CHILD"
        if len(args) == 1 and str(type(args[0])) == "<class '__main__.Parent'>":
            new_args = []
            new_args.extend([args[0].x, args[0].y, args[0].z])
            print "HIJACKING"
            return Child(*new_args)
        print "RETURNING FROM NEW IN CHILD"
        return object.__new__(cls, *args, **kwds)
Run Code Online (Sandbox Code Playgroud)

但是当我跑步的时候

B = Child(A) 
Run Code Online (Sandbox Code Playgroud)

我明白了:

NEW'ING CHILD  
HIJACKING  
NEW'ING CHILD  
RETURNING FROM NEW IN CHILD  
INITILIZING PARENT  
Traceback (most recent call last):  
  File "classes.py", line 52, in <module>  
    B = Child(A)  
TypeError: __init__() takes exactly 4 arguments (2 given) 
Run Code Online (Sandbox Code Playgroud)

看起来hack的工作方式与我预期的一样,但编译器最后会抛出一个TypeError.我想知道我是否可以重载TypeError使其忽略B = Child(A)习语,但我不知道该怎么做.在任何情况下,您能否告诉我您从实例继承的解决方案?

谢谢!

Ale*_*lli 7

一旦__new__在课堂上Child返回的实例Child,Child.__init__将被称为(使用相同的参数__new__给出)在该实例上-显然它只是继承Parent.__init__,这并不需要很好地被称为只有一个ARG(另Parent,A).

如果没有其他方法Child可以进行,你可以定义一个Child.__init__接受一个arg(它忽略)或三个(在这种情况下它调用Parent.__init__).但是放弃__new__并且拥有所有逻辑更简单Child.__init__,只需要Parent.__init__恰当地调用!

使用代码示例来具体化:

class Parent(object):

    def __init__(self, x, y, z):
        print "INITIALIZING PARENT"
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return "%s(%r, %r, %r)" % (self.__class__.__name__,
            self.x, self.y, self.z)


class Child(Parent):

    _sentinel = object()

    def __init__(self, x, y=_sentinel, z=_sentinel):
        print "INITIALIZING CHILD"
        if y is self._sentinel and z is self._sentinel:
            print "HIJACKING"
            z = x.z; y = x.y; x = x.x
        Parent.__init__(self, x, y, z)
        print "CHILD IS DONE!"

p0 = Parent(1, 2, 3)
print p0
c1 = Child(p0)
print c1
c2 = Child(4, 5, 6)
print c2
Run Code Online (Sandbox Code Playgroud)


Len*_*bro 6

好的,所以我没有意识到你对我的解决方案的静态副本感到高兴,直到我已经完成了我的解决方案.但我决定不浪费它,所以无论如何它在这里.与其他解决方案的不同之处在于,即使更新了它,它实际上也会从父级获取属性.

_marker = object()

class Parent(object):

    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

class Child(Parent):

    _inherited = ['x', 'y', 'z']

    def __init__(self, parent):
        self._parent = parent
        self.a = "not got from dad"

    def __getattr__(self, name, default=_marker):
        if name in self._inherited:
            # Get it from papa:
            try:
                return getattr(self._parent, name)
            except AttributeError:
                if default is _marker:
                    raise
                return default

        if name not in self.__dict__:
            raise AttributeError(name)
        return self.__dict__[name]
Run Code Online (Sandbox Code Playgroud)

现在,如果我们这样做:

>>> A = Parent('gotten', 'from', 'dad')
>>> B = Child(A)
>>> print "a, b and c is", B.x, B.y, B.z
a, b and c is gotten from dad

>>> print "But x is", B.a
But x is not got from dad

>>> A.x = "updated!"
>>> print "And the child also gets", B.x
And the child also gets updated!

>>> print B.doesnotexist
Traceback (most recent call last):
  File "acq.py", line 44, in <module>
    print B.doesnotexist
  File "acq.py", line 32, in __getattr__
    raise AttributeError(name)
AttributeError: doesnotexist
Run Code Online (Sandbox Code Playgroud)

有关此更通用的版本,请查看http://pypi.python.org/pypi/Acquisition包.事实上,在某些情况下,这是一种血腥的需求解决方案.


ely*_*ase 6

我发现这个(封装)是最干净的方式:

class Child(object):
    def __init__(self):
        self.obj = Parent()

    def __getattr__(self, attr):
        return getattr(self.obj, attr)
Run Code Online (Sandbox Code Playgroud)

这样您就可以使用所有 Parent 的方法和您自己的方法,而不会遇到继承问题。

  • 在尝试了这里的所有选项之后,这绝对是我一直在寻找的解决方案。最干净、最简单,永远不需要知道变量名称。强烈推荐。 (2认同)