我想知道在基类方法中使用子类变量(本例中为self.sub_resource
)的常见方法是什么?
版本1和版本2似乎工作相同,但版本1的代码较少,但self.sub_resource
在pycharm中突出显示为Unresolved attribute reference 'sub_resource' for class 'Base'
那么哪种变体更可取呢?还有其他的优缺点吗?
# Version 1:
class Base():
def __init__(self):
self.base_resource = 'Base.resource'
print('Base.__init__')
def predict(self):
print('Base.predict() start')
self.forward()
print('Used in Base.predict():', self.base_resource)
print('Used in Base.predict():', self.sub_resource)
print('Base.predict() end')
def forward(self):
raise NotImplementedError
class A(Base):
def __init__(self):
super().__init__()
self.sub_resource = 'A.sub_resource'
print('A.__init__')
def forward(self):
print('A.forward() start')
print('Used in A.forward():', self.base_resource)
print('Used in A.forward():', self.sub_resource)
print('A.forward() end')
print('-' * 60)
a = A()
a.predict()
# Version 2:
class Base():
def __init__(self, sub_resource):
self.sub_resource = sub_resource
self.base_resource = 'Base.resource'
print('Base.__init__')
def predict(self):
print('Base.predict() start')
self.forward()
print('Used in Base.predict():', self.base_resource)
print('Used in Base.predict():', self.sub_resource)
print('Base.predict() end')
def forward(self):
raise NotImplementedError
class A(Base):
def __init__(self):
self.sub_resource = 'A.sub_resource'
super().__init__(self.sub_resource)
print('A.__init__')
def forward(self):
print('A.forward() start')
print('Used in A.forward():', self.base_resource)
print('Used in A.forward():', self.sub_resource)
print('A.forward() end')
print('-' * 60)
a = A()
a.predict()
版本2是正确的方法。这允许子类扩展基类而不声明sub_resource
属性。
解释器需要确保该属性存在。这就是pycharm在版本1中突出显示这一行的原因。在执行过程中,子类的值将优先于基类。
理想的做法是在基类中声明所有被访问的属性,然后在子类中必要的地方重写它。