2010-08-18 59 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

相关问题