2010-08-18 58 views
3

我在修改某些類型的可重用類中有一些代碼。這是一個簡化版本。API可以告訴Pylint不要在客戶端代碼中抱怨嗎?

class Foo: 
    def __init__(self): 
     self.count = 0 

    def increment(self): 
     self.count += 1 

# Add another method outside of the class definition. 
# Pylint doesn't care about this, and rates this file 10/10. 

Foo.__dict__["current_count"] = lambda self: self.count 

在真正的代碼,「CURRENT_COUNT」是一個變量,而不是一個固定的字符串,這就是爲什麼我沒有寫:

Foo.current_count = lambda self: self.count # Cannot do in my scenario. 

現在,當我的客戶來使用新功能,Pylint在恐怖中上下跳動。

import server_api 

def main(): 
    foo_count = server_api.Foo() 
    foo_count.increment() 


    print foo_count.current_count() 
    # Pylint complains here: 
    #  E1101: 8:main: Instance of 'Foo' has no 'current_count' member 
    # I don't want to have to tell pylint to disable that message in every client. 

main() 

每一個使用這個新函數的類都會受到懲罰,並且我被迫在每個引用中禁用這個消息。如果有這個類的未知引用,我會在API中放一些代碼來告訴Pylint寒冷。

唉,pylint文檔是... ummm ...沒有質量有利於我的理解,我一直無法找到任何建議。

所以煮沸:我可以告訴pylint在我的API代碼中關閉與此類相關的E1101規則,只要客戶端引用它?還有其他解決方案嗎?

+0

我沉默了很多Pylint的投訴,這對我來說也是一個有趣的問題。 – Eike 2010-08-18 07:13:37

回答

5

,這裏是我的解決方案靈感來自例如ActiveState cookbook recipe,在Yoni Hanswer中提供。

到Foo類,我加了這個無用的__getattr__方法。

def __getattr__(self, name): 
    # This is only called when the normal mechanism fails, so in practice should never be called. 
    # It is only provided to satisfy pylint that it is okay not to raise E1101 errors in the client code. 
    raise AttributeError("%r instance has no attribute %r" % (self, name)) 

這應該與以前的版本幾乎沒有區別。它不應該在正常的事件過程中被調用,但它足以說服pylint對這個錯誤保持安靜。

p.s.你可以抱怨這個代碼不是很漂亮。我分享這個意見。但我認爲它爲客戶帶來的好處勝過其代碼味道。

0

務實地說,爲什麼pylint(或任何皮棉)應該保持沉默的假設?鑑於假陽性和假陰性之間存在偏差,棉絨應該更喜歡前者。在我看來,因爲Pylint表示它的結果是人們認爲它應該被最大化的分數,但是沒有「獲勝」的獎項。

另一方面,它抱怨的構造肯定是醜陋的。我明白server_api爲了方便起見而被簡化了,但是你真的需要關注模塊名稱空間嗎?從您的客戶端代碼看來,current_count方法名稱是硬編碼的,爲什麼不在服務器中?

+4

每個誤報都是噪音的來源,這使得回顧日誌變得更加困難。如果你有很多這樣的人,你就會想要儘可能多地保持沉默,以便只關注真正的問題。 – 2010-08-18 07:23:36

+0

有兩個信噪比需要優化。 第一個是積極的:警告中的誤報。我喜歡明確地關閉導致它的警告,表明我已經評估了pylint的說法,並確定它不適用或者是值得的折衷。這阻止我一次又一次地重新評估決策,並且意味着來自pylint的任何警告都需要注意。 另一個是code:pylint pragmas。額外的編譯指示使代碼不易讀,生成速度也較慢。這就是我在這裏工作的。 – Oddthinking 2010-08-18 07:34:53

+0

在真實的代碼中,它是Enumerated類型的又一個變體。我希望能夠將類型稱爲TrafficLight.RED而不是TrafficLight [「RED」],或者爲了類型安全性和效率的原因,甚至可以使用「RED」。因此運行時將標識符添加到類中。 (在「編譯」時間做它會違反DRY。) – Oddthinking 2010-08-18 07:38:55

2

繼您的評論,因爲你要爲枚舉類型,爲什麼不看一看at this SO question,或this ActiveState cookbook recipe

出於個人喜好,我會選擇添加枚舉類型到類,就像在SO question其中一個答案(無恥複製的情況下):

class Animal: 
    def __init__(self, name): 
     self.name = name 

    def __str__(self): 
     return self.name 

    def __repr__(self): 
     return "<Animal: %s>" % self 

Animal.DOG = Animal("dog") 
Animal.CAT = Animal("cat") 
+0

ActiveState Cookbook解決方案很有趣。它使用\ _ \ __ getattr \ _ \ _(),這似乎是閉嘴Pylint的投訴。我甚至可以使用直通解決方案來關閉Pylint,同時像內置操作一樣。 – Oddthinking 2010-08-18 14:45:24

+0

複製的代碼是我如何使用它,但它不能滿足我的很多要求。你重複自己(動物出現6次,狗出現兩次,每種類型和枚舉值相乘)。沒有通過值的迭代。你不能檢查使用「in」(雖然你可以使用isinstance,這是相似的)。沒有辦法將字符串解析爲適當的類型。如果repr()是可評估的,那會更好。 – Oddthinking 2010-08-18 14:51:36

+0

我認爲你錯誤地解釋了「不要重複自己」的意圖。這不是一個詞彙禁止令,因爲如果使用'logging.debug()'將是犯罪行爲。 「動物」出現頻率無關緊要;堅持DRY,Animal.DOG擁有單一的權威代表就足夠了。在它的例子中。如果您需要'in'和'next'繼承'Animal(list)'或參見http://stackoverflow.com/questions/3487434/overriding-append-method-after-inheriting-from-a-python-list/3488283 #3488283 – msw 2010-08-18 16:36:15

相關問題