Python中的派生类和基类的属性? [英] Python derived class and base class attributes?

查看:362
本文介绍了Python中的派生类和基类的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有似乎对此没有很好的在线文档:
如果我做一个派生类,会自动将其拥有的基类的所有属性?但是,什么是在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆