pylint的“公开方法太少”消息是什么意思


110

我在某些代码上运行pylint,并收到错误“公共方法太少(0/2)”。此消息是什么意思?该pylint的文档也没有什么帮助:

当类的公共方法太少时使用,因此请确保它确实值得。


1
你的班级什么样?除了存储数据之外,该类还做其他事情吗?
Blender

1
该类所做的只是存储数据。
monsur 2012年

2
好吧,那是你的问题。类并不意味着存储数据。这就是字典和列表之类的数据结构的用途。
Blender

有趣,谢谢!可以使pylint错误消息更加有用。无论如何,请随时将您的评论变成答案,我会批准。
monsur 2012年

6
但是“很少”的定义在哪里?我只有一种方法。这就是该类存在的原因。pylint如何定义“少量”?大于2?为什么?
Zordid

Answers:


124

该错误基本上表明类并不意味着存储数据,因为您基本上将类视为字典。类至少应具有几种方法来处理它们所保存的数据。

如果您的班级看起来像这样:

class MyClass(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

考虑使用字典或namedtuple替代字典。尽管如果一堂课似乎是最好的选择,请使用它。pylint并不总是知道什么是最好的。

请注意,这namedtuple是不可变的,实例化时分配的值以后不能修改。


72
+1表示“插条不知道最好的”-使用您自己的判断,但通常,如果您需要的是“结构”,请使用dictnamedtuple。当您想向对象添加一些逻辑时使用一个类(例如,您希望在创建对象时发生一些事情,在添加对象时需要发生一些特殊的事情,您想要对它执行一些操作,控制其发生方式显示,等等)
Burhan Khalid

感谢您的详细回复!我的用例类似于Burhan提到的用例,我在创建数据时正在对数据进行一些处理。
monsur 2012年

6
如果您在类定义中包含Meta(元类),则此错误没有意义。
alexander_ch 2015年

11
namedtuple很烂-除了语法丑陋之外,您无法记录下来或轻松提供默认值。
rr-

6
每次使用后,namedtuple我都会后悔这个决定。允许命名访问和索引访问属性都是不一致的。
theorifice

39

如果您要扩展课程,那么我的建议是系统地禁用此警告并继续进行,例如,在Celery任务中:

class MyTask(celery.Task):  # pylint: disable=too-few-public-methods                                                                                   
    """base for My Celery tasks with common behaviors; extends celery.Task

    ...             

即使仅扩展单个函数,您也绝对需要一个类来使该技术起作用,并且扩展绝对比黑客第三方类更好!


有了这个可行的,预先提交的建议,现在可以给我:错误的期权价值'too-few-public-method'(bad-option-value)
水星

您是否在方法中添加了“ s”?您的错误选项值消息中没有该消息。
圣人

4
禁用此功能的更好方法是在配置文件min-public-methods=0[BASIC]部分中进行设置。这使您可以将其与所有disable=内容(放在[MESSAGE CONTROL])中中,我发现可以更轻松地添加有关启用和禁用内容以及配置更改原因的详细注释。
cjs

15

这是pylint的盲目规则的另一种情况。

“类并不意味着存储数据”-这是一个错误的陈述。字典并不能满足所有需求。类的数据成员是有意义的,字典项是可选的。证明:您可以dictionary.get('key', DEFAULT_VALUE)防止KeyError,但__getattr__默认情况下不简单。

编辑-使用结构的推荐方法

我需要更新我的答案。现在-如果需要a struct,则有两个不错的选择:

a)只需使用 attrs

这些是为此的库:

https://www.attrs.org/en/stable/

import attr

@attr.s
class MyClass(object):  # or just MyClass: for Python 3
    foo = attr.ib()
    bar = attr.ib()

您得到的额外好处是:不编写构造函数,默认值,验证__repr__,只读对象(namedtuples即使在Python 2中也要替换),等等。

b)使用dataclasses(Py 3.7+)

根据hwjp的评论,我还建议 dataclasses

https://docs.python.org/3/library/dataclasses.html

这几乎和 attrs,并且是标准的库机制(“包含电池”),没有额外的依赖关系,但Python 3.7+除外。

上一个答案的其余部分

NamedTuple并不是很好-特别是在python 3之前typing.NamedTuplehttps : //docs.python.org/3/library/typing.html#typing.NamedTuple- 您一定要检查“从NamedTuple模式”。namedtuples从字符串描述创建的Python 2 丑陋,糟糕,并且“在字符串文字中编程”是愚蠢的。

我同意两个当前的答案(“考虑使用其他东西,但是pylint并不总是正确的” –接受的答案,以及“使用pylint抑制评论”),但是我有自己的建议。

让我再指出一次:一些类意味着 用于存储数据。

现在还要考虑的选项-使用property-ies。

class MyClass(object):
    def __init__(self, foo, bar):
        self._foo = foo
        self._bar = bar

    @property
    def foo(self):
        return self._foo

    @property
    def bar(self):
        return self._bar

在上面,您具有只读属性,对于Value Object来说,这是可以的(例如,像域驱动设计中的属性),但是您也可以提供setter-这样,您的类将能够对自己拥有的字段负责进行一些验证等。(如果有设置器,则可以在构造函数中使用它们进行赋值,即self.foo = foo代替Direct self._foo = foo,但要小心,设置器可能会假定其他字段已经初始化,然后需要在构造函数中进行自定义验证) 。


2
在Python 3.7及更高版本中,数据类提供了一个很好的解决方案,解决了namedtuple的某些丑陋之处,它们非常适合DDD Value Objects。
hwjp

我同意,从2020年开始,这是标准的做法。要使用宽版本范围的机制(我记得还记得,2.7、3.3 +),可以使用该attrs库,它实际上是创建dataclasses模块的蓝图。
Tomasz Gandor

namedtuples对于继承有奇怪的语法...要求每个使用一个类的类都知道这是一个命名的元组,并使用__new__代替__init__dataclasses没有这个限制
Erik Aronesty '19

4

当老板期望单一责任原则时,这很困难,但皮林特拒绝了。因此,请向您的班级添加第二种方法,以使您的班级违反单一责任原则。在旁观者的眼中,您打算采取多大责任的原则。

我的解决办法

我在类中添加了一个额外的方法,因此它现在可以完成两件事。

def __str__(self):
    return self.__class__.__name__

我只是想知道我是否现在需要将我的班级分成2个单独的文件,也许还有模块。

问题得到了解决,但我的同事们却没有花一整天的时间讨论规范,而不是像生死攸关的问题那样坚持下去。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.