如何在Python中基类内创建派生类的对象?

时间:2016-04-01 15:20:58

标签: python inheritance

我有这样的代码:

class Base:
    def __init__(self):
        pass

    def new_obj(self):
        return Base()  # ← return Derived()

class Derived(Base):
    def __init__(self):
        pass

在带注释的行中,我实际上并不想要Derived对象,而是self实际上是类的任何对象。

以下是Mercurial的真实示例。

怎么做?

4 个答案:

答案 0 :(得分:8)

def new_obj(self):
    return self.__class__()

答案 1 :(得分:3)

我想不出一个非常好的理由这样做,正如D.Shawley指出的那样:

def new_obj(self):
    return self.__class__()

会这样做。

这是因为在派生类上调用方法时,如果该类上不存在该方法,它将使用方法解析顺序来确定在其继承链上调用哪个方法。在这种情况下,你只有一个,所以它将调用Base.new_obj并传入实例作为第一个参数(即self)。

所有实例都有__class__属性,该属性引用它们所属的类。所以给出了

 class Base:
     def new_obj(self):
          return self.__class__()

 class Derived(Base): pass

 derived = Derived()

以下几行在功能上是等效的:

 derived.new_obj()
 # or
 Base.new_obj(derived)

如果您忘记将self参数添加到函数声明中,或者没有为函数提供足够的参数,并且看到如下所示的堆栈跟踪,则可能遇到过此类的亲戚:< / p>

>>> f.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 2 arguments (1 given)

答案 2 :(得分:0)

您也可以使用使用装饰器创建的类方法来执行此操作。

In [1]: class Base:
   ...:     @classmethod
   ...:     def new_obj(cls):
   ...:         return cls()
   ...:

In [2]: class Derived(Base): pass

In [3]: print type(Base.new_obj())
<type 'instance'>

In [4]: print Base.new_obj().__class__
__main__.Base

In [5]: print Derived.new_obj().__class__
__main__.Derived

顺便说一句(您可能知道这一点),如果您不对它们做任何事情,则不必创建__init__方法。

答案 3 :(得分:0)

您可以使用classmethod:

class Base:
    def __init__(self):
        pass

    @classmethod
    def new_obj(cls):
        return cls()

class Derived(Base):
    def __init__(self):
        pass

>>> b = Base()
>>> b.new_obj()
<__main__.Base at 0x10fc12208>
>>> d = Derived()
>>> d.new_obj()
<__main__.Derived at 0x10fdfce80>
相关问题