Python约定建议使用下划线继续保护属性的名称。据我所知,受保护的属性只应在给定的类及其子类中使用。当我尝试在备用初始化器中使用受保护的属性时,你能否为我提供一些关于为什么pylint返回 protected-access 警告的直觉,例如。
class Test(object):
def __init__(self, name):
self.name = name
self._count = 0
self._bound = 1 # max value
@classmethod
def specific_state(cls, name, bound):
test = cls(name)
test._bound = bound
我确实理解在这个特定的情况下(在上面的例子中给出)我处理一个对象的实例,但它仍然在类定义中,因此从我的角度看似乎没问题。在这个问题上,pylint是否过于严格,还是我误解了?
答案 0 :(得分:2)
在我看来,pylint
在这一点上过于活跃。我怀疑在这方面会有太多不同意见。我无法为pylint开发人员说话,但我会猜测这对于类型推理来说更像是一个问题,而不一定被认为是他们的理想行为。
不同的人可能会告诉您关于引用带有下划线的成员的不同意见。我的个人意见是
所以这意味着,如果我在Foo
中定义了类_member
(包含成员foo.py
),并且我创建了Foo
的子类(让我们调用它{{ 1}})在Bar
中,我不相信bar.py
应该明确引用Bar
属性。但是,如果您将_member
移至Bar
,那么就可以了。事实上,也应该允许班级foo.py
(也在Baz
中定义)依赖foo.py
的内部 - 但最好有充分的理由这样做。
大多数情况下,我对下划线前缀成员的处理方式并不好,因为"受保护" (在Java意义上)。我认为它们应被视为"实施细节"。受保护在Java中工作得更好,因为如果您更改实现(例如删除受保护的成员),代码将在编译时失败并让您知道您的子类所依赖的受保护成员不再存在。 Python没有内置的安全防护装置。
因为下划线带有前缀的名称是"实现细节",如果它是同一个类(就像你在问题中描述的那样),那么它是相同的实现,所以(对我来说,允许访问这些成员是一个明智的选择。我Foo
没有第二个想法: - )。
答案 1 :(得分:1)
pylint.checkers.classes.ClassChecker
方法中的_check_protected_attribute_access
:
'''Given an attribute access node (set or get), check if attribute
access is legitimate. Call _check_first_attr with node before calling
this method. Valid cases are:
* self._attr in a method or cls._attr in a classmethod. Checked by
_check_first_attr.
* Klass._attr inside "Klass" class.
* Klass2._attr inside "Klass" class when Klass2 is a base class of
Klass.
'''
您可以在上述案例中看到您的案例。因此可以假设protected-access
警告是合法的。
可是:
pylint
代码本身的发生了完全相同的情况。 (例如exceptions.py:338):
# pylint: disable=protected-access
exc = exc._proxied
所以基本上他们在那种情况下禁用了他们的检查员。
在c ++中,以下代码有效:
class X
{
private:
int a;
protected:
int b;
public:
static void staticMethod(X& x)
{
x.a = 1;
x.b = 1;
}
};
因此,访问静态方法中的protected / private成员是有效的。
我想说pylint
在这种情况下过于敏感。您可以使用注释来禁用那里的检查器。产生警告的原因可能是静态检查器难以实现更复杂的行为。