简体   繁体   English

比较 Python 中父子 class 的属性

[英]Compare attributes of parent and child class in Python

I have a Python class like this:我有一个 Python class 像这样:

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        

My goal is to use A as an abstract class where the child classes are forced to implement __val2 .我的目标是将A用作抽象 class ,其中子类被迫实现__val2

I create a child class B :我创建了一个孩子 class B

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

When I initialize an object of class B , this error is thrown:当我初始化 class B的 object 时,会抛出此错误:

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

I tried modifying B like this:我尝试像这样修改B

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

But this throws the same exception.但这会引发相同的异常。

Trying the same but with super :尝试相同但使用super

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

But this throws another error:但这会引发另一个错误:

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

What is the Pythonic way do handle this kind of abstraction?处理这种抽象的 Pythonic 方式是什么? How should validate() be implemented so that it checks for __val2 ?应该如何实现validate()以便检查__val2

When you use double preceding underscores for your class attribute names, python converts them to _<classname>_<varname> .当您对 class 属性名称使用双前下划线时, python 会将它们转换为_<classname>_<varname> So in your case, A.__val2 becomes A._A__val2 and B.__val2 becomes B._B__val2 , which means they won't share the same name.因此,在您的情况下, A.__val2变为A._A__val2并且B.__val2变为B._B__val2 ,这意味着它们不会共享相同的名称。 See the link Thierry Lathuille has shared in the comment on your question, and here's the link to python docs: https://docs.python.org/3/tutorial/classes.html#private-variables .请参阅 Thierry Lathuille 在您的问题的评论中分享的链接,这里是 python 文档的链接: https://docs.python.org/3/tutorial.html/privateclasses.html/privateclasses.html

You can fix this by not using double underscores, so go for something like _val2 or val2 .您可以通过不使用双下划线来解决此问题,因此 go 用于_val2val2之类的东西。

There are a few other issues in your code: all your class methods need self as the first argument, and you need to access them by calling self.<method_name> .您的代码中还有一些其他问题:您的所有 class 方法都需要self作为第一个参数,您需要通过调用self.<method_name>来访问它们。 So to access validate , you need to call it with self.validate() .因此,要访问validate ,您需要使用self.validate()调用它。 Also, the second arg to hasattr must be a string.此外, hasattr的第二个参数必须是字符串。

Here's an updated example that should fix your issue:这是一个更新的示例,应该可以解决您的问题:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM