2016-06-26 23 views
2

Python约定建议使用下划线继续保护属性的名称。据我了解,受保护的属性只能在给定的类及其子类中使用。那么您能否告诉我为什么当我尝试在替代初始值设定项中使用受保护属性时,为什么pylint会返回受保护访问警告?classmethod中的受保护属性

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有点太严格了,还是我误解了?

回答

1

_check_protected_attribute_access方法pylint.checkers.classes.ClassChecker

'''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警告是合法的。

但是:

  1. pylint S码本身发生完全相同的情况。 (例如exceptions.py:338):

    # pylint: disable=protected-access 
    exc = exc._proxied 
    

    所以基本上他们在这种情况下禁用了他们的检查器。

  2. 在C++下面的代码是有效的:

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

    静态方法,以便访问受保护/私有成员是有效的。

我要说的是pylint过于在这种情况下sensitiv。您可以使用注释来禁用检查器。警告产生的原因可能是静态检查器执行更复杂的行为很难。

2

在我看来,pylint在这个上太过于活跃了。我怀疑在这方面会有太多的分歧。我不能为pylint开发人员说话,但我会猜想这种类型推理的问题更多,而不一定被认为是他们理想的行为。


不同的人可能会告诉你引用带下划线的成员的不同意见。我个人的看法是,

  • 如果是在同一模块中,这是公平的游戏
    • 但是,你还是要努力限制这一尽可能避免搭售类/函数如有可能,一起实施。
  • 如果该成员属于不同的模块,它不再是公平的游戏,并应被视为实现细节。
    • 将这些实现绑在一起本质上是危险的,因为对一个实现的更改很容易在没有警告的情况下破坏其他代码。

因此,这意味着,如果我有类Foo(与成员_member)在foo.py定义,如果我做的Foo子类(可以称之为Bar)在bar.py,我不相信Bar应该明确提及_member属性。但是,如果您将Bar转换为foo.py,则表示正常。事实上,类Baz(也定义在foo.py)也应该被允许依赖于Foo的内部 - 但它最好有一个很好的理由这样做。

大多数情况下,对于下划线前缀成员作为“受保护”(在Java意义上)的处理,我并不确定。我认为它们应该被视为“实施细节”。在Java中受保护的工作更好,因为如果更改实现(例如,移除受保护的成员),代码将在编译时失败,并让您知道子类依赖的受保护成员不在那里。 Python没有内置这样的安全防护。因为下划线前缀名称是“实现细节”,如果它是相同的类(就像你在你的问题中描述的情况一样),那么它就是相同的实现,因此(对我来说)允许访问这些成员是一个“闻风而动。我想# pylint: disable=protected-access,没有第二个想法:-)。