我今天做了一些测试:
class SuperC():
def __init__(self, a, b, c, d='D0'):
self.A = a
self.B = b
self.C = c
self.D = d
self.E = 'E0'
sup = SuperC('A0', 'B0', 'C0')
print(sup.A) # >>> A0
print(sup.B) # >>> B0
print(sup.C) # >>> C0
print(sup.D) # >>> D0
print(sup.E) # >>> E0
你可以在超类中看到,有两种类型的默认值(d
和e
)
d
更开放,而e
有点隐藏'
现在,如果我创建一个子类,使用新属性' f':
class SubC1(SuperC):
def __init__(self, a, b, c, f):
super().__init__(a, b, c)
self.F = f
sub1 = SubC1('A1', 'B1', 'C1', 'F1')
print(sub1.A) # >>> A1
print(sub1.B) # >>> B1
print(sub1.C) # >>> C1
print(sub1.D) # >>> D0
print(sub1.E) # >>> E0
print(sub1.F) # >>> F1
我可以看到a
,b
,c
获得了良好的继承,并且可以接受新值。
但我没有在d
选择e
和super().__init__()
。但是它们也有完美的继承,问题是我在创建子类的实例时无法更改d
和e
的值。 f
工作正常。
现在我创建了另一个子类:
class SubC2(SuperC):
def __init__(self, a, b, c, f, d='D2'):
super().__init__(a, b, c, d)
self.F = f
sub2 = SubC2('A2', 'B2', 'C2', 'F2')
print(sub2.A) # >>> A2
print(sub2.B) # >>> B2
print(sub2.C) # >>> C2
print(sub2.D) # >>> D2
print(sub2.E) # >>> E0 # hidden e is still E0
print(sub2.F) # >>> F2
在d
和__init__()
中都写有super().__init__()
,现在d可以获得完美的继承,并且可以在新实例中使用新的默认值或新值覆盖。但是e
仍然是E0
似乎唯一的好方法是:
class SubC3(SuperC):
def __init__(self, a, b, c, f, d='new D', e='new E'):
super().__init__(a, b, c)
self.D = d # set new
self.E = e # set new
self.F = f
sub3 = SubC3('A3', 'B3', 'C3', 'F3')
print(sub3.A) # >>> A3
print(sub3.B) # >>> B3
print(sub3.C) # >>> C3
print(sub3.D) # >>> new D
print(sub3.E) # >>> new E
print(sub3.F) # >>> F3
既然我可以同时使用全新的默认值/实例值d
和e
,但如果不显示,那么它们将不会从SuperC继承
我的问题是,我认为这是正确的方法吗? 我错过了什么吗? 有没有更好的方法来设置默认值继承?
或者在某种程度上,如果以这种方式编写,e
不应该被更改?因为它可能是一个基本属性,应该是超类和子类的常量值?
答案 0 :(得分:1)
我似乎无法理解这个问题......
执行此操作时:
class SuperC():
def __init__(self, a, b, c, d='D0'):
self.A = a
self.B = b
self.C = c
self.D = d
self.E = 'E0'
self.E
不是“隐藏”的。它刚刚收到一个硬编码值:字符串"E0"
和d='D0'
可以读作如果在d
参数中使用特定值调用,请使用该值,否则,只需使用字符串"D0"
(它是named optional argument)
执行此操作时:
class SubC3(SuperC):
def __init__(self, a, b, c, f, d='new D', e='new E'):
super().__init__(a, b, c)
self.D = d # set new
self.E = e # set new
self.F = f
正在发生的事情是,对super().__init__
的调用会创建一个类,其中包含您传递的a, b, c
个参数,self.E
和硬编码的"E0"
。之后,执行self.E = e
,然后使用参数"E0"
的值覆盖e
。
试试这个:
class SubC3(SuperC):
def __init__(self, a, b, c, f, d='new D', e='new E'):
super().__init__(a, b, c)
print("Before overwrite=%s" % self.E)
self.D = d # set new
self.E = e # set new
print("After overwrite=%s" % self.E)
self.F = f
sub3 = SubC3('A3', 'B3', 'C3', 'F3')
您会在初始化后看到self.E
为"E0"
然后被覆盖:
Before overwrite=E0
After overwrite=new E
关于d
:
试试这个:
class SubC3(SuperC):
def __init__(self, a, b, c, f, d='new D', e='new E'):
super().__init__(a, b, c)
self.E = e # set new
self.F = f
sub3 = SubC3('A3', 'B3', 'C3', 'F3')
print(sub3.D)
你会看到它是D0
,因为你没有将任何d
传递给超级,而你没有在SubC3.__init__
中覆盖它,所以它使用了默认值SuperC.__init__
(你在哪里d='D0'
)