2016-06-26 331 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,沒有第二個想法:-)。