在Python中,带有一个下划线前缀表示不应在其类之外访问成员。 这似乎是基于每个类的,例如 Java 和 C++。
但是,pylint 似乎在每个对象的基础上强制执行此约定。 有没有办法允许每个班级访问而不诉诸
#pylint: disable=protected-access
?
class A:
def __init__(self):
self._b = 5
def __eq__(self, other):
return self._b == other._b
结果:
pylint a.py
a.py:6: W0212(protected-access) Access to a protected member _b of a client class
Pylint 在此处描述了该消息。
pylint 不知道
other
是什么类型(应该如何,您可以将 A 的实例与所有内容进行比较),因此出现警告。我认为没有办法禁用警告。
您可以通过在该行附加
# pylint: disable=W0212
来仅禁用该行的警告。
Christian Geier 关于为什么会出现错误以及如何禁用它的说法是正确的。
不过,我鼓励您考虑更改代码:pylint 告诉您一些重要的事情。从您的示例代码来看,您似乎想使用 eq 将 A 类的对象与 A 类的其他对象进行比较,但您的示例不能保证调用者不会尝试
A() == C()
。当您检查 True
时返回 Circle()._radius == Sphere._radius
似乎可能会导致问题。
请参阅此 stackoverflow 线程,了解如何处理此问题的讨论。
__eq__
方法问题的第一部分已在许多帖子中得到解决:
__eq__
方法应该能够将您的A
实例与其他类型的任意对象进行比较,而不仅仅是与其他A
实例进行比较。这是推荐的实施方式__eq__
:
class A:
def __init__(self, value) -> None:
self.__private = value
def __eq__(self, other) -> bool:
if not isinstance(other, A):
return NotImplemented
return <logic to compare two A instances>
备注:
或者,您可能要求
other
属于相同的基类:type(other) == A
,它比 isinstance(...)
版本更严格(后者也允许子类)。
在某些示例中,使用
isinstance(other, self.__class__)
或 type(self) == type(other)
,但这通常是错误的:当 B() == C()
和 NotImplemented
是 B
的两个不同子类时,C
会给出 A
。
有些人还在类
__class__
的定义主体中使用 A
来表示 A
。虽然它在 python 中运行良好,但 mypy 给出了 error: Name "__class__" is not defined [name-defined]
。
如果
self
和other
没有可比性,建议返回NotImplemented
。但是,type(NotImplemented)
不应该包含在__eq__
的返回类型提示中,只需将其保留为bool
即可。
问题的第二部分是关于受保护属性的比较,没有 pylint 显示“受保护访问”错误。如果你想比较以双下划线开头的私有属性,由于名称修改,它会变得更加混乱:
other.__private
表示类getattr(other, '_A__private')
体内的A
,与类中定义的other.__private
无关。类的主体B
(意思是getattr(other, '_B__private')
)。即使 B
是 A
的真正子类,属性 _A__private
也只能用于 A
方法访问,而不能用于 B
方法。考虑到这一点,在我们确保 B
是 A
的子类之后,我们可能想要将 self.__private
与 other.__private
进行比较。
dict
对象逐项进行比较,并且存储为 A
的类 _A__private
的私有属性也可以正确访问,而 pylint 不会抱怨受保护的访问。但是,如果子类与基类相比具有额外的属性,则比较结果始终为False
。另外,如果定义了 __slots__
,则没有 __dict__
属性。 return self.__dict__ == other.__dict__
other
属于同一类,并且理论上访问私有属性是安全的,我们也必须手动静音 pylint。 return self.__private == other.__private # pylint: disable=W0212
getattr()
,但明确引用 python 的名称修饰应该是一些丑陋黑客的警告信号。另请注意,当 other.__private
(或更确切地说 AttributeError
)未在 __private
上定义时,_A__private
会引发 other
,而 getattr()
会默默地返回 None
。 return self.__private == getattr(other, '_A__private')
return other.cmp_private(self.__private)
def cmp_private(self, value) -> bool:
return self.__private == value