2017-02-26 49 views
0

我试图使用增强而不是重写基类的子类。我正在使用super方法来调用基类。我发现我需要使用__init__中的名称修改功能(但仅在init中)才能使代码正常工作。因此,我做了这个打印的例子。因为我没有使用名字改编我期望它来调用子类两次,当我做初始化,而是调用基类在__init__中的python名称mangling似乎不一致

似乎__init__有时出现的基类,有时看到子类。我相信这只是我的一个不完全的理解,但是当我在打印示例中调用基类和子类时,是否需要为真实代码命名?

代码

class base: 
    def __init__(self): 
     self.print() 

    def print(self): 
     print("base") 

class subclass(base): 
    def __init__(self): 
     super(subclass, self).__init__() 
     self.print() 

    def print(self): 
     super(subclass, self).print() 
     print("subclass") 

x = base() 
x.print() 
print("--") 
y = subclass() 
y.print() 

输出 - 为什么不y = subclass()打印subclass而不是base,因为我没有使用名字改编?

> ./y.py 
base 
base 
-- 
base 
subclass 
base 
subclass 
base 
subclass 

断码的时候我不使用名称改编,作品,当我用self.__set__set = set(注释代码)。它得到以下错误,当我不使用__set

File "./x.py", line 5, in __init__ 
    self.set(arg) 
TypeError: set() missing 1 required positional argument: 'arg2' 

代码:

class base: 
    def __init__(self, arg): 
     self.set(arg) 
     # self.__set(arg) 

    # __set = set 

    def set(self, arg): 
     self.arg = arg 

    def print(self): 
     print("base",self.arg) 

class subclass(base): 
    def __init__(self, arg1, arg2): 
     super(subclass, self).__init__(arg1) 
     self.set(arg1, arg2) 

    def set(self, arg1, arg2): 
     super(subclass, self).set(arg1) 
     self.arg2 = arg2 

    def print(self): 
     super(subclass, self).print() 
     print("subclass", self.arg2, self.arg) 

x = base(1) 

x.print() 
x.set(11) 
x.print() 

y = subclass(2,3) 

y.print() 
y.set(4,5) 
y.print() 

======= =======更新

我重写了代码看起来像这样:

class base: 
    def __init__(self): 
     print("base init") 
     self.print() 

    def print(self): 
     print("base print") 

class subclass(base): 
    def __init__(self): 
     print("sc init") 
     super(subclass, self).__init__() 
     print("sc after super") 
     self.print() 

    def print(self): 
     print("subclass print start") 
     super(subclass, self).print() 
     print("subclass print") 

y = subclass() 
print("--") 
y.print() 

,当我跑我得到这个输出:

sc init 
base init 
subclass print start <<<< why is the subclass print called here 
base print 
subclass print 
sc after super 
subclass print start 
base print 
subclass print 
-- 
subclass print start 
base print 
subclass print 

为什么当我启动子类时,底层init中的self.print调用子类打印?我期待那个打印基地。当我在init之外调用它时,它会调用基本打印。

回答

2

子类print明确调用父之一。所以每次调用subclass.print时,都会打印出“base”和“subclass”。这发生三次,因为您拨打print方法三次:subclass.__init__,base.__init__(调用subclass.__init__)和subclass.print(它调用超类的版本)。

在您的“设置”示例中,subclass.__init__调用base.__init__,它尝试仅使用一个参数调用self.set。但是由于您正在实例化subclass,self.setsubclass.set,它有两个参数。

目前还不清楚你试图用这些例子来达到什么目的。您的子类并不需要致电base.__init__,因为所有可以做的事情是致电base.set,并且您已从subclass.set调用该子类。所以,即使您的所有通话都成功了,也会导致某些方法被多次呼叫,就像print示例一样。

我的印象是,你有点被带走并试图让每个方法调用它的超类版本。这并不总是一个好主意。如果你编写了一个子类,并且它调用了一个超类方法,那么你需要确保子类仍然提供一个与超类所期望的接口兼容的接口。如果没有,你可能需要而不是调用超类方法,而是让子类将其“内联”功能结合起来(尽管如果世界上的其他类已经对基类如何做出假设,这可能会更危险作品)。结果是你总是需要考虑哪些方法称为哪些人;你不能随便调用每一个超类方法,并期待它的工作。

+0

我打电话给两个打印看看会发生什么。我正在研究调用超类版本来理解流程。我认为你打我的问题,虽然。基类有一个arg,而子类有两个。当我试图通过超级调用基类时,该方法有2个参数,并且没有匹配。我将不得不考虑那一刻。仍然有点困惑,为什么名字mangling使它的工作。 – kdubs

+0

@kdubs:这个名字让它变得可行,因为在名称改变的情况下,这个方法的每个版本本质上是分开的,并且不能被子类覆盖。所以每个类都会一直在调用它自己的实现。但这通常不是你想要的,因为子类不能覆盖基类实现。基本的问题是你不能采用一个需要一个参数的方法,并用一个需要两个参数的方法来覆盖它;任何用一个调用它的代码现在都会失败。 (在很多情况下,这可以通过为第二个参数给出默认值来处理。) – BrenBarn

+0

请参阅我的更新。打印在init函数中的调用不会按照我期望的方式工作 – kdubs

相关问题