python 基类是什么_Python派生类和基类的属性?

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?

解决方案

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()

This will cause the following error:

AttributeError: 'Bar' object has no attribute 'a'

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()

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).

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.

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.

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()

which would print 20.

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()

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__.

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).

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). Briefly, super delegates the method call to the next class in the method resolution order - the MRO (which in single inheritance is the parent class). See the documentation on super for more info.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值