gpt4 book ai didi

python - 派生类是否自动拥有基类的所有属性?

转载 作者:IT老高 更新时间:2023-10-28 20:23:46 24 4
gpt4 key购买 nike

似乎没有关于此的好的在线文档:
如果我创建一个派生类,它会自动拥有基类的所有属性吗?但什么是BaseClass.__init()因为,你还需要对其他基类方法这样做吗?是否BaseClass.__init__()需要争论吗?如果你的基类有参数 __init__() , 它们是否也被派生类使用,是否需要显式设置派生类的参数 __init__() ,或将它们设置为 BaseClass.__init__()反而?

最佳答案

如果您实现 __init__在从 BaseClass 派生的类中,它将覆盖继承的 __init__方法等BaseClass.__init__永远不会被调用。如需调用__init__ BaseClass 的方法(通常是这种情况),然后由您来执行此操作,并通过调用 BaseClass.__init__ 显式完成,通常来自新实现的 __init__方法。

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__也被覆盖了。我们通过显式调用 Foo.__init__ 来解决这个问题。从内部 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正如预期的那样。 Foo.__init__在这种情况下,需要一个参数,它是 Foo 的一个实例(按照惯例称为 self )。

通常,当您在类的实例上调用方法时,类实例会自 Action 为第一个参数传递。类实例上的方法称为绑定(bind)方法。 bar.do_something是一个绑定(bind)方法的例子(你会注意到它是在没有任何参数的情况下调用的)。 Foo.__init__是一个未绑定(bind)的方法,因为它没有附加到 Foo 的特定实例上,所以第一个参数是 Foo 的一个实例, 需要显式传递。

在我们的例子中,我们通过 selfFoo.__init__ ,这是 Bar 的实例传递给 __init__ Bar 中的方法.自 Bar继承自 Foo , Bar 的实例也是 Foo 的实例,所以路过 selfFoo.__init__被允许。

很可能是您继承的类需要或接受更多的参数,而不仅仅是类的实例。这些将像处理您在 __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 .

如果您试图实现一个通过继承类完全公开基类的所有初始化参数的接口(interface),则需要明确地这样做。这通常使用 *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方法明确。讨论 super是另一个问题,但我只想说,在这些情况下,它通常用于通过调用 BaseClass.method(self) 来完成正在执行的操作。 .简而言之, super将方法调用委托(delegate)给方法解析顺序中的下一个类 - MRO(在单继承中是父类)。见 documentation on super了解更多信息。

关于python - 派生类是否自动拥有基类的所有属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6396452/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com