[英]How to create object of derived class inside base class in Python?
I have a code like this: 我有这样的代码:
class Base:
def __init__(self):
pass
def new_obj(self):
return Base() # ← return Derived()
class Derived(Base):
def __init__(self):
pass
In the line with a comment I actually want not exactly the Derived
object, but any object of class that self
really is. 在带注释的行中,我实际上并不想要
Derived
对象,而是self
真正的类的任何对象。
Here is a real-life example from Mercurial . 以下是Mercurial的真实案例。
How to do that? 怎么做?
def new_obj(self):
return self.__class__()
I can't think of a really good reason to do this, but as D.Shawley pointed out: 我想不出有这么好的理由, 但正如D.Shawley指出的那样:
def new_obj(self):
return self.__class__()
will do it. 会做的。
That's because when calling a method on a derived class, if it doesn't exist on that class, it will use the method resolution order to figure out which method to call on its inheritance chain. 这是因为在派生类上调用方法时,如果该类上不存在该方法,它将使用方法解析顺序来确定在其继承链上调用哪个方法。 In this case, you've only got one, so it's going to call
Base.new_obj
and pass in the instance as the first argument (ie self). 在这种情况下,你只有一个,所以它将调用
Base.new_obj
并将实例作为第一个参数传递(即self)。
All instances have a __class__
attribute, that refers to the class that they are an instance of. 所有实例都有一个
__class__
属性,该属性引用它们是其实例的类。 So given 所以给定
class Base:
def new_obj(self):
return self.__class__()
class Derived(Base): pass
derived = Derived()
The following lines are functionally equivalent: 以下几行在功能上是等效的:
derived.new_obj()
# or
Base.new_obj(derived)
You may have encountered a relative of this if you've either forgotten to add the self
parameter to your function declaration, or not provided enough arguments to a function and seen a stack trace that looks like this: 如果您忘记将
self
参数添加到函数声明中,或者没有为函数提供足够的参数,并且看到如下所示的堆栈跟踪,则可能遇到过此函数的亲戚:
>>> f.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 2 arguments (1 given)
You can use a classmethod: 你可以使用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>
You can also do this with a class method, which you create with a decorator. 您也可以使用类方法执行此操作,该方法是使用装饰器创建的。
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
Incidentally (you may know this), you don't have to create __init__
methods if you don't do anything with them. 顺便说一句(你可能知道这一点),如果你不对它们做任何事情,就不必创建
__init__
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.