我有这样的代码:
class Base:
def __init__(self):
pass
def new_obj(self):
return Base() # ← return Derived()
class Derived(Base):
def __init__(self):
pass
在带注释的行中,我实际上并不想要Derived
对象,而是self
实际上是类的任何对象。
以下是Mercurial的真实示例。
怎么做?
答案 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>