代码之家  ›  专栏  ›  技术社区  ›  Georg Schölly Crazy Developer

是否应该调用父类的?

  •  113
  • Georg Schölly Crazy Developer  · 技术社区  · 15 年前

    我在Objective-C中使用了这个结构:

    - (void)init {
        if (self = [super init]) {
            // init class
        }
        return self;
    }
    

    __init__ ?

    class NewClass(SomeOtherClass):
        def __init__(self):
            SomeOtherClass.__init__(self)
            # init class
    

    __new__() __del__() ?

    Inheritance and Overriding __init__ in Python

    6 回复  |  直到 5 年前
        1
  •  151
  •   mpowcode Anon    5 年前

    如果你需要super的东西 __init__ 除了在当前类的 __init__, 你必须自己称呼它,因为这不会自动发生。但是如果你不需要super的任何东西 __一开始, 没必要叫它。例子:

    >>> class C(object):
            def __init__(self):
                self.b = 1
    
    
    >>> class D(C):
            def __init__(self):
                super().__init__() # in Python 2 use super(D, self).__init__()
                self.a = 1
    
    
    >>> class E(C):
            def __init__(self):
                self.a = 1
    
    
    >>> d = D()
    >>> d.a
    1
    >>> d.b  # This works because of the call to super's init
    1
    >>> e = E()
    >>> e.a
    1
    >>> e.b  # This is going to fail since nothing in E initializes b...
    Traceback (most recent call last):
      File "<pyshell#70>", line 1, in <module>
        e.b  # This is going to fail since nothing in E initializes b...
    AttributeError: 'E' object has no attribute 'b'
    

    __del__ 也是一样,(但要小心依赖 __德尔__ 最终确定-考虑通过使用语句来代替它。

    __new__. 所有的初始化都是在 __init__.

        2
  •  116
  •   Bruce    7 年前

    在Anon的回答中:
    “如果你需要super's的东西 __init__ 除了在当前类的 ,您必须自己称呼它,因为这不会自动发生”

    令人难以置信的是:他的措辞完全违背了继承的原则。


    并非如此 “来自super's的东西 (…)不会自动发生“ ,它会自动发生,但不会发生,因为基类 __初始化__ 由派生CLA的定义覆盖

    那么,为什么要定义派生的_类呢 __初始化__ ,因为当有人诉诸继承时,它覆盖了其目标??

    这是因为需要定义在基类的 __初始化__ __初始化__ 功能。
    换句话说,, __初始化__ 此外 __初始化__ 如果后者没有被覆盖。


    __初始化__ 在实例化时不再激活。为了抵消这种失活,需要做一些特殊的事情:显式调用基类的 __初始化__ 为了 ,不添加,由基类的 __初始化__ 这正是官方文件中所说的:

    派生类中的重写方法实际上可能希望 而不是简单地替换基类方法 同名的。 有一种直接调用基类方法的简单方法:just 调用BaseClassName.methodname(self,参数)。
    http://docs.python.org/tutorial/classes.html#inheritance

    故事就是这样:

    • __初始化__ 派生类中的函数

    • 当目标是替换基类执行的初始化时, __初始化__ 必须在派生类中定义

    • __初始化__


        3
  •  70
  •   Nick Rempel    6 年前

    在Python中,调用超类的 __init__ 是可选的。如果调用它,那么是否使用 super 标识符,或是否显式命名超类:

    object.__init__(self)
    

    对于对象,调用超级方法并不是绝对必要的,因为超级方法是空的。同样适用于 __del__

    另一方面 __new__

        4
  •  20
  •   SilentGhost    15 年前

    编辑
    我们无法告诉你是否需要打电话给你父母 __init__ (或任何其他功能)。没有这样的调用,继承显然会起作用。这完全取决于代码的逻辑:例如,如果 __初始化__ 总共

    考虑下面的例子:

    >>> class A:
        def __init__(self, val):
            self.a = val
    
    
    >>> class B(A):
        pass
    
    >>> class C(A):
        def __init__(self, val):
            A.__init__(self, val)
            self.a += val
    
    
    >>> A(4).a
    4
    >>> B(5).a
    5
    >>> C(6).a
    12
    
        5
  •  5
  •   Vinay Sajip    15 年前

    更新: 相同的基本逻辑适用于任何方法调用。构造函数有时需要特别考虑(因为它们通常设置决定行为的状态)和析构函数,因为它们与构造函数并行(例如在资源分配中,例如数据库连接)。但是,比方说,这同样适用于 render() 小部件的方法。

    进一步更新: 什么是OPP?你是说哎呀?否-子类通常需要知道 某物 protected 在OOP中通常是一个有效的概念(当然,在Python中不是)。

        6
  •  4
  •   u0b34a0f6ae    15 年前

    依我看,你应该叫它。如果你的超类是 object __init__

        7
  •  3
  •   Shital Shah    6 年前

    是的,您应该始终调用基类 __init__ 明确地说,这是一种良好的编码实践。忘记这样做可能会导致微妙的问题或运行时错误。这是真的,即使 __初始化__ 不接受任何参数。这与编译器为您隐式调用基类构造函数的其他语言不同。Python不会这么做!

    总是调用基类的主要原因 _init__ 基类通常可以创建成员变量并将其初始化为默认值。所以,如果不调用基类init,则不会执行任何代码,并且最终得到的基类没有成员变量。

    :

    class Base:
      def __init__(self):
        print('base init')
    
    class Derived1(Base):
      def __init__(self):
        print('derived1 init')
    
    class Derived2(Base):
      def __init__(self):
        super(Derived2, self).__init__()
        print('derived2 init')
    
    print('Creating Derived1...')
    d1 = Derived1()
    print('Creating Derived2...')
    d2 = Derived2()
    

    Creating Derived1...
    derived1 init
    Creating Derived2...
    base init
    derived2 init
    

    Run this code