Python classmethod中的受保护属性

Python classmethod中的受保护属性,python,attributes,class-method,pylint,Python,Attributes,Class Method,Pylint,Python惯例建议在受保护属性的名称中加下划线。据我所知,受保护的属性只能在给定的类及其子类中使用。然后,你能告诉我为什么当我尝试在替代初始值设定项中使用受保护的属性时,pylint会返回受保护的访问警告吗 class Test(object): def __init__(self, name): self.name = name self._count = 0 self._bound = 1 # max value @cl

Python惯例建议在受保护属性的名称中加下划线。据我所知,受保护的属性只能在给定的类及其子类中使用。然后,你能告诉我为什么当我尝试在替代初始值设定项中使用受保护的属性时,pylint会返回受保护的访问警告吗

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开发人员说话,但我想这更多的是类型推断的问题,而不是被认为是他们的理想行为


对于引用以下划线开头的成员,不同的人可能会告诉您不同的意见。我个人的意见是

  • 如果它在同一个模块中,这是公平的游戏
    • 然而,您仍然应该尽可能地限制这一点,以避免在可能的情况下将类/函数实现捆绑在一起
  • 如果成员属于不同的模块,则不再公平,应将其视为实现细节。
    • 在这里将实现捆绑在一起本质上是危险的,因为对一个实现的更改很容易在没有警告的情况下破坏另一个代码
因此,这意味着如果我在
Foo.py
中定义了类
Foo
(带有成员
\u成员
),并且如果我在
Bar.py
中创建了
Foo
(让我们称之为
Bar
)的子类,我不认为
Bar
应该明确引用
\u成员
属性。但是,如果您将
Bar
移动到
foo.py
中,那么就可以了。事实上,类
Baz
(也在
foo.py
中定义)也应该允许依赖
foo
的内部结构——但最好有一个好的理由这样做

大多数情况下,我不同意将带下划线前缀的成员视为“受保护”(在Java意义上)。我认为它们应该被视为“实施细节”。Protected在Java中工作得更好,因为如果您更改实现(例如,删除一个受保护的成员),代码将在编译时失败,并让您知道您的子类所依赖的受保护成员不再存在。Python没有内置这样的安全防护


因为下划线前缀的名称是“实现细节”,如果它是同一个类(如您在问题中描述的情况),那么它就是同一个实现,因此(对我来说)允许访问这些成员是一件轻而易举的事。我想
#pylint:disable=protected access
不经再三考虑:-)。

来自
pylint.checkers.classes.ClassChecker
中的
检查受保护的属性\u 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.
'''
您可以看到您的案例不在上述案例中。因此,我们可以假设
受保护访问
警告是合法的

但是:

  • pylint
    s代码本身来看,发生了完全相同的情况。(例如,例外情况py:338):

    所以在这种情况下,他们基本上禁用了他们的on checker

  • 在C++中,下面的代码是有效的:

            class X
    {
    private:
        int a;
    protected:
        int b;
    public:
        static void staticMethod(X& x)
        {
            x.a = 1;
            x.b = 1;
        }
    };
    
    因此,在静态方法中访问受保护/私有成员是有效的

    我想说,在这种情况下,
    pylint
    过于敏感。您可以使用注释禁用那里的检查器。产生警告的原因可能是静态检查器很难实现更复杂的行为

            class X
    {
    private:
        int a;
    protected:
        int b;
    public:
        static void staticMethod(X& x)
        {
            x.a = 1;
            x.b = 1;
        }
    };