首页 > 解决方案 > 比较Python中父类和子类的属性

问题描述

我有一个这样的 Python 类:

class A:
  __val1: float = 0.0
  __val2: float

  def __init__():
     validate()

  def validate() -> bool:
     if not hasattr(self, __val2): # how is this supposed to be done?
         raise NotImplementedError()
     return self.__val1 >= self.val2        

我的目标是A用作一个抽象类,子类被强制实现__val2

我创建了一个子类B

class B(A):
  __val2 = 1.0
  
  def __init__():
     super().__init__()

当我初始化 class 的对象时B,会引发此错误:

E   AttributeError: 'B' object has no attribute '_A__val2'

我试过B 这样修改:

class B(A):
  A.__val2 = 1.0
  [...]

但这会引发相同的异常。

尝试相同但使用super

class B(A):
  super.__val2 = 1.0
  [...]

但这会引发另一个错误:

E   TypeError: can't set attributes of built-in/extension type 'super'

处理这种抽象的 Pythonic 方式是什么?应该如何validate()实施以便检查__val2

标签: pythonoop

解决方案


当您在类属性名称中使用前面的双下划线时,python 会将它们转换为_<classname>_<varname>. 因此,在您的情况下,A.__val2becomeA._A__val2B.__val2become B._B__val2,这意味着它们不会共享相同的名称。请参阅 Thierry Lathuille 在对您的问题的评论中分享的链接,这里是 python 文档的链接:https ://docs.python.org/3/tutorial/classes.html#private-variables 。

您可以通过不使用双下划线来解决此问题,因此请使用_val2or之类的东西val2

您的代码中还有一些其他问题:您的所有类方法都需要self作为第一个参数,并且您需要通过调用来访问它们self.<method_name>。所以要访问validate,你需要用self.validate(). 此外,第二个 arg tohasattr必须是字符串。

这是一个更新的示例,应该可以解决您的问题:

class A:
  _val1: float = 0.0
  _val2: float

  def __init__(self):
     self.validate()

  def validate(self) -> bool:
     if not hasattr(self, '_val2'):
         raise NotImplementedError()
     return self._val1 >= self._val2

class B(A):
  _val2 = 1.0

  def __init__(self):
     super().__init__()

print(B()._val2)

推荐阅读