lia*_*l1i 24 python inheritance attributes class derived
似乎没有好的在线文档:如果我创建一个派生类,它会自动拥有基类的所有属性吗?但是有什么用呢BaseClass.__init(),你还需要对其他基类方法做吗?是否BaseClass.__init__()需要论证?如果您有基类的参数__init__(),它们是否也被派生类使用,您是否需要显式设置派生classe的参数__init__(),或者将它们设置为BaseClass.__init__()?
Hen*_*all 58
如果__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()
Run Code Online (Sandbox Code Playgroud)
这将导致以下错误:
AttributeError: 'Bar' object has no attribute 'a'
Run Code Online (Sandbox Code Playgroud)
因此,该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()
Run Code Online (Sandbox Code Playgroud)
10按预期打印.Foo.__init__在这种情况下,需要一个参数,它是一个实例Foo(按惯例调用self).
通常,当您在类的实例上调用方法时,类实例将作为第一个参数自动传递.类实例上的方法称为绑定方法.bar.do_something是绑定方法的一个例子(你会注意到它是在没有任何参数的情况下调用的).Foo.__init__是一个未绑定的方法,因为它没有附加到特定的实例Foo,因此第一个参数,一个实例Foo,需要显式传递.
在我们的例子中,我们传递self给Foo.__init__,这是Bar传递给__init__方法的实例Bar.由于Bar继承自Foo,实例Bar也是实例Foo,因此允许传递self给它们Foo.__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()
Run Code Online (Sandbox Code Playgroud)
哪个会打印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()
Run Code Online (Sandbox Code Playgroud)
在这种情况下,参数c设置为40,因为它是第一个参数Bar.__init__.然后,将第二个参数被结合到变量args和kwargs(*和**是特定语法说展开列表/元组或字典成单独的参数传递给一个函数/方法时),以及为传递Foo.__init__.
此示例还指出,如果需要(在本例中),则需要显式调用任何重写方法do_something.
最后一点,您将经常看到super(ChildClass, self).method()(其中ChildClass有一些任意子类)而不是BaseClass显式调用该方法.讨论super是另一个问题,但足以说明,在这些情况下,它通常用于完成通过呼叫完成的工作BaseClass.method(self).简而言之,super将方法调用委托给方法解析顺序中的下一个类--MRO(在单继承中是父类).有关详细信息,请参阅super上的文档.
Cat*_*lus 11
如果我创建一个派生类,它会自动拥有基类的所有属性吗?
类属性,是的.实例属性,否(仅仅因为它们在创建类时不存在),除非__init__在派生类中没有,在这种情况下将调用基类,并将设置实例属性.
是BaseClass.init()需要参数吗?
取决于课程及其__init__签名.如果您Base.__init__在派生类中显式调用,则至少需要传递self作为第一个参数.如果你有
class Base(object):
def __init__(self):
# something
Run Code Online (Sandbox Code Playgroud)
然后很明显,没有其他论据被接受__init__.如果你有
class Base(object):
def __init__(self, argument):
# something
Run Code Online (Sandbox Code Playgroud)
然后你必须argument在调用base时传递__init__.这里没有火箭科学.
如果您的基类init()有参数,它们是否也被派生类使用,您是否需要显式设置派生classe的init()的参数,或者将它们设置为BaseClass.init()而不是?
同样,如果派生类没有__init__,则将使用基础类.
class Base(object):
def __init__(self, foo):
print 'Base'
class Derived(Base):
pass
Derived() # TypeError
Derived(42) # prints Base
Run Code Online (Sandbox Code Playgroud)
在其他情况下,你需要以某种方式照顾它.您是否使用*args, **kwargs并且只是将未修改的参数传递给基类,或者复制基类签名,或者从其他地方提供参数,取决于您要完成的任务.
| 归档时间: |
|
| 查看次数: |
41045 次 |
| 最近记录: |