派生类是否自动具有基类的所有属性?

| 似乎没有关于此的好的在线文档: 如果我创建派生类,它将自动具有基类的所有属性吗?但是ѭ0的作用是什么,您还需要对其他基类方法进行处理吗?
BaseClass.__init__()
需要论证吗?如果您有基类
__init__()
的参数,派生类也使用它们吗,是否需要将参数显式设置为派生类的
__init__()
或将其设置为
BaseClass.__init__()
?     
已邀请:
        如果在从BaseClass派生的类中实现
__init__
,则它将覆盖继承的
__init__
方法,因此将永远不会调用
BaseClass.__init__
。如果您需要为BaseClass调用
__init__
方法(通常是这种情况),那么您就可以做到这一点,通常通过在新实现的
__init__
方法中调用calling7ѭ来明确地做到这一点。
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
方法已按预期方式继承,但是该方法要求已设置属性ѭ14,,这绝不是因为
__init__
也被覆盖了。我们通过在
Bar.__init__
内显式调用
Foo.__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()
按预期打印print19ѭ。在这种情况下,
Foo.__init__
需要一个单独的参数,该参数是
Foo
的实例(按照惯例称为convention22ѭ)。 通常,当您在类的实例上调用方法时,该类实例将作为第一个参数自动传递。类实例上的方法称为绑定方法。
bar.do_something
是绑定方法的一个示例(您会注意到它被调用时没有任何参数)。
Foo.__init__
是未绑定的方法,因为它未附加到
Foo
的特定实例,因此第一个参数argument21ѭ的实例需要显式传递。 在我们的例子中,我们将
self
传递给
Foo.__init__
,这是
Bar
的实例,并已在
Bar
中传递给
__init__
方法。由于
Bar
继承自
Foo
,因此
Bar
的实例也是also21ѭ的实例,因此允许将
self
传递给
Foo.__init__
。 您从中继承的类很可能需要或接受的参数不仅仅是该类的实例。这些问题的处理方式与您在ѭ5范围内调用的任何方法一样:
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
。 如果您要尝试实现一个通过继承类完全公开基类的所有初始化参数的接口,则需要明确地这样做。通常使用* args和** kwargs参数(名称是按惯例)完成的,它们是未明确命名的所有其他参数的占位符。以下示例利用了我已经讨论的所有内容:
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,因为它是
Bar.__init__
的第一个参数。然后将第二个参数合并到变量
args
kwargs
中(*和**是特定语法,表示传递给函数/方法时,将列表/元组或字典扩展为单独的参数),然后传递给
Foo.__init__
。 此示例还指出,如果需要,则必须显式调用任何被覆盖的方法(在这种情况下为
do_something
)。 最后一点,您经常会看到使用
super(ChildClass, self).method()
(其中
ChildClass
是任意的子类)而不是显式调用
BaseClass
方法。对ѭ51的讨论是另一个完全不同的问题,但足以说,在这种情况下,通常将其用于完全通过调用ѭ52来完成所要做的事情。简而言之,“ 51”按方法解析顺序将方法调用委托给下一个类-MRO(在单个继承中为父类)。有关更多信息,请参见super上的文档。     
如果我创建派生类,它将自动具有基类的所有属性吗? 类属性,是的。实例属性,否(仅因为创建类时它们不存在),除非派生类中没有ѭ5,,在这种情况下将调用基类,并设置实例属性。   BaseClass.init()是否需要参数? 取决于类别及其its5ѭ签名。如果您在派生类中显式调用
Base.__init__
,则至少需要传递
self
作为第一个参数。如果你有
class Base(object):
    def __init__(self):
        # something
显然,“ 5”没有接受其他论点。如果你有
class Base(object):
    def __init__(self, argument):
        # something
则呼叫基数
__init__
时必须通过
argument
。这里没有火箭科学。   如果您有基类init()的参数,派生类也使用它们,是否需要将参数显式设置为派生类的init()或将其设置为BaseClass.init()呢? ? 同样,如果派生类没有
__init__
,将使用基数代替。
class Base(object):
    def __init__(self, foo):
        print \'Base\'

class Derived(Base):
    pass

Derived()   # TypeError
Derived(42) # prints Base
在其他情况下,您需要以某种方式进行处理。是否使用ѭ65并仅将未经修改的参数传递给基类,还是复制基类签名,还是从其他位置提供参数,取决于您要完成的工作。     

要回复问题请先登录注册