Python中的派生类和基类的属性? [英] Python derived class and base class attributes?
问题描述
有似乎对此没有很好的在线文档:
如果我做一个派生类,会自动将其拥有的基类的所有属性?但是,什么是在 BaseClass的.__的init()
对,你还需要将它做其他的基类的方法?是否 BaseClass的.__的init __()
需要的参数?如果你对你的基类参数 __的init __()
,他们是否也使用派生类,你需要明确设置参数派生CLASSE的 __ __的init()
,或将它们设置为 BaseClass的.__的init __()
呢?
There seems to be no good online documentation on this:
If I make a derived class, will it automatically have all the attributes of the base class? But what's the BaseClass.__init()
for, do you also need to do it to other base class methods? Does BaseClass.__init__()
need arguments? If you have arguments for your base class __init__()
, are they also used by the derived class, do you need to explicitly set the arguments to the derived classe's __init__()
, or set them to BaseClass.__init__()
instead?
推荐答案
如果您实施 __的init __
从BaseClass的派生类,那么它将覆盖继承 __ __的init
法等 BaseClass的.__的init __
将永远不会被调用。如果您需要调用 __的init __
为BaseClass的方法(这是通常的情况),那么它给你做到这一点,它明确地调用完成 BaseClass的.__的init __
,通常是从内新实施的 __ __的init
方法。
If you implement __init__
in a class derived from BaseClass, then it will overwrite the inherited __init__
method and so BaseClass.__init__
will never be called. If you need to call the __init__
method for BaseClass (as is normally the case), then its up to you to do that, and its done explicitly by calling BaseClass.__init__
, normally from within the newly implemented __init__
method.
class Foo(object):
def __init__(self):
self.a = 10
def do_something(self):
print self.a
class Bar(Foo):
def __init__(self):
self.b = 20
bar = Bar()
bar.do_something()
这将导致以下错误:
AttributeError: 'Bar' object has no attribute 'a'
因此, do_something
方法已经被继承的预期,但该方法需要属性 A
一直集,它永远不会是因为 __ __的init
也被覆盖。我们避开这个问题通过显式调用富.__的init __
从内部酒吧.__的init __
。
So, the do_something
method has been inherited as expected, but that method requires the attribute a
to have been set, which it never is because __init__
was also overwritten. We get round this by explicitly calling Foo.__init__
from within Bar.__init__
.
class Foo(object):
def __init__(self):
self.a = 10
def do_something(self):
print self.a
class Bar(Foo):
def __init__(self):
Foo.__init__(self)
self.b = 20
bar = Bar()
bar.do_something()
这版画 10
预期。 富.__的init __
在这种情况下,只需要一个参数,它是富
(其中按照惯例被称为<$实例C $ C>自)。
which prints 10
as expected. Foo.__init__
in this case expects a single argument which is an instance of Foo
(which by convention is called self
).
通常,当你调用一个方法在类的一个实例,类实例即自动第一个参数传递。在一个类的实例方法被调用的绑定方法的。 bar.do_something
是一个绑定方法的一个例子(你会注意到它被称为不带任何参数)。 富.__的init __
是绑定方法的,因为它没有连接到富
,所以第一个参数,富
,需要明确的被传递。
Normally, when you call a method on an instance of a class, the class instance is passed automatically as the first argument. Methods on an instance of a class are called bound methods. bar.do_something
is an example of a bound method (and you'll note that it is called without any arguments). Foo.__init__
is an unbound method because it is not attached to a particular instance of Foo
, so the first argument, an instance of Foo
, needs to be passed explicitly.
在我们的例子中,我们通过自
到富.__的init __
,这是<$ C $实例C>酒吧传递给了 __ __的init
方法酒吧
。由于酒吧
从富
继承,酒吧
的实例也富
的实例,因此通过自
到富.__的init __
是允许的。
In our case, we pass self
to Foo.__init__
, which is the instance of Bar
that was passed to the __init__
method in Bar
. Since Bar
inherits from Foo
, instances of Bar
are also instances of Foo
, so passing self
to Foo.__init__
is allowed.
这很可能是因为您是从继承类需要或接受多个参数的类的实例的情况。这些被处理,你会与你从内 __在调用init __
的任何方法:
It is likely be the case that the class you are inheriting from requires or accepts more arguments than just an instance of the class. These are dealt with as you would with any method you're calling from within __init__
:
class Foo(object):
def __init__(self, a=10):
self.a = a
def do_something(self):
print self.a
class Bar(Foo):
def __init__(self):
Foo.__init__(self, 20)
bar = Bar()
bar.do_something()
这将打印 20
。
如果你想实现一个通过你的继承类充分暴露了基类的所有初始化参数的接口,你需要明确这样做。这通常与*指定参数和**完成kwargs参数(名字都按照约定),这是对于没有明确命名的参数其余所有的占位符。下面的示例使用的一切我已经讨论过的:
If you're trying to implement a interface that fully exposes all the initialisation arguments of the base class through your inheriting class, you'll need to do so explicitly. This is typically done with the *args and **kwargs arguments (the names are by convention), which are placeholders for all rest of the arguments that aren't explicitly named. The following example makes use of everything I've discussed:
class Foo(object):
def __init__(self, a, b=10):
self.num = a * b
def do_something(self):
print self.num
class Bar(Foo):
def __init__(self, c=20, *args, **kwargs):
Foo.__init__(self, *args, **kwargs)
self.c = c
def do_something(self):
Foo.do_something(self)
print self.c
bar = Bar(40, a=15)
bar.do_something()
在这种情况下,参数 C
设置为40,因为它是第一个参数酒吧.__的init __
。然后第二个参数被纳入变量 ARGS
和 kwargs
(*和**是说,扩大特定语法列表/元组或字典成单独的参数传递时,函数/方法),并传递给富.__的init __
。
In this case, the argument c
is set to be 40, as it's the first argument to Bar.__init__
. The second argument is then incorporated into the variables args
and kwargs
(the * and ** is specific syntax that says expand the list/tuple or dictionary into separate arguments when passing to a function/method), and is passed on to Foo.__init__
.
这个例子也使得该的的覆盖方法需要显式调用,如果这是需要什么(如 do_something
的一点是在本情况)。
This example also makes the point that any overwritten method needs to be called explicitly if that is what is required (as do_something
is in this case).
最后一点,你会经常看到超(ChildClass,个体经营)。方法()
(其中 ChildClass
一些任意的子类)中使用,而不是明确的的BaseClass
方法的调用。 超级
的讨论是完全是另外一个问题,但我只想说,在这些情况下,它通常被用来做什么是由调用完成 BaseClass.method(个体经营)
。请参阅超的文档获取更多信息。
One final point, you will often see super(ChildClass, self).method()
(where ChildClass
is some arbitrary child class) being used instead of a call to the BaseClass
method explicitly. Discussion of super
is a whole other question, but suffice it to say, in these cases it's typically being used to do exactly what is being done by calling BaseClass.method(self)
. See the documentation on super for more info.
这篇关于Python中的派生类和基类的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!