如何处理 Pylint 的 "too-many-instance-attributes" 错误信息?

81

我刚刚尝试使用Pylint对一些代码进行了检查,最后只剩下一个错误。

R0902: too-many-instance-attributes (8/7)

我理解限制实例属性数量的原因,但是七个似乎有点少。我也意识到语法检查器不应该有最后的决定权。然而,我想知道我应该做什么,而不是:

def __init__(self, output_file=None, output_dir=None):
    """
    Set the frobnicator up, along with default geometries
    """

    self.margin = 30

    self.pos = [0, 0]
    self.sep = [5, 5]

    self.cell = [20, 20]

    self.frobbr = library.Frobbr()

    page = self.frobbr.get_settings('page')

    self.lim = [page.get_width() - self.margin,
                page.get_height() - self.margin]

    self.filename = output_file
    self.moddir = output_dir

我应该将几何图形打包成字典,还是采取其他措施以防止Pylint抱怨,或者只是忽略它(我不想这样做)?


8
这可能更适合在CodeReview上。另外,考虑使用元组来表示固定大小的值,如位置。 - Colonel Thirty Two
3
你可以将self.moddirself.filename合并成一个名为self.output_path的属性。它可以是一个字符串,例如os.path.join(self.moddir, self.filename),也可以是一个元组(self.moddir, self.filename) - user2555451
1
我能在我的回答中添加什么内容以获得采纳吗,@Inductiveload?我通常不会这样问,但是这个问题和答案对众多人有所帮助,选中标记可能有助于向其他访问者保证这是一个合理的方法。 - Zero Piraeus
不,我不知道为什么那个答案以前从未被接受,它是一个好的答案。我想这是因为我的粗心维护! - Inductiveload
4个回答

115

代码审查工具的职责是让你意识到可能存在的问题,正如你在问题中所说,它不应该有最后的决定权。

如果你已经考虑过pylint的建议,并且决定对于这个类来说,你拥有的属性是合适的(我觉得这很合理),你可以通过向你的类添加一个禁用注释来抑制错误并表明你已经考虑了这个问题:

class Frobnicator:

    """All frobnication, all the time."""

    # pylint: disable=too-many-instance-attributes
    # Eight is reasonable in this case.

    def __init__(self):
        self.one = 1
        self.two = 2
        self.three = 3
        self.four = 4
        self.five = 5
        self.six = 6
        self.seven = 7
        self.eight = 8

这样,你既不会忽视Pylint,也不会成为它的奴隶;你是在使用它作为有用但可能出错的工具。

默认情况下,当你本地禁用一个检查时,Pylint会产生一条信息性的消息:

 Locally disabling too-many-instance-attributes (R0902) (locally-disabled)

您可以通过以下两种方式之一来防止该消息出现:

  1. 在运行pylint时添加一个disable=标志:

  2. $ pylint --disable=locally-disabled frob.py 
    
  3. pylintrc配置文件中添加指令:

  4. [MESSAGES CONTROL]
    disable = locally-disabled
    

除了拼写错误外,这就是我要找的东西。请注意,pylint将报告您正在忽略此设置,因此:与开发人员忽略警告或通知需要相同的努力。 - ThorSummoner
12
@ThorSummoner - 当然,但是如果你追求10分满分的话,那就会有很大的区别啦! :-) - MrWonderful
3
这也会对 CI 产生影响,因为它会影响 pylint 的退出代码。 - Spain Train
3
拥有过多的本地变量或实例可能存在什么潜在问题?@Zero Piraeus - alper
2
@alper 这是一种更通用的“代码异味”;它本身并没有错,但这是一种简单(不准确)的衡量复杂性的方式。如果一个类太复杂了,那么也许你在一个类中做了太多的事情。所以当linter抱怨这个问题时,这是一个很好的提醒,要检查这个类是否只负责一件事,或者是否可以拆分。 - Philip Couling

36

这是一种意识形态上的反对,但个人倾向于尽可能使此类更改普适化。如果一个文件中7个不足够的实例,而我选择在这里允许它,为什么不在其他地方也一样呢?我并非总是全面更改代码检查规则,但至少会考虑这一点。因此,如果你想进行全面的更改,在你的 .pylintrc 文件中,在 DESIGN 部分更改 max-attributes=7。

由于我认为7在全面范围内有点低,所以我进行了更改:

[DESIGN]
max-attributes=7

max-attributes=12

2
我能理解你的论点,但我的方法略有不同。 为什么不到处都这样做呢?因为我想将特殊类保持为特殊,而不是在一般情况下允许更多。 然而,问题仍然存在,所以我的禁用pylint注释总是跟着一个注释,解释为什么该类需要那么多属性。 - Ali Rasim Kocal
是的,我同意,我使用两种方法的混合。但当我必须做出个别例外时,我总是评估是否应该在所有地方都做出这样的例外(通常情况下,除非有非常充分的理由,否则我倾向于使用普遍例外而不是仅限于某些情况)。 - Bob

8
来自Zero Piraeus的答案很好。话说,由于你在init方法中提供的上下文很少,甚至没有一个真正的类名,所以很难确定,但我想文件名和moddir与边距、位置等无关。
I/O操作通常最好被隔离到函数中而不是放入方法中。它们经常有许多不同的格式和序列化选项,大部分时间你不想将它们与你的对象逻辑(方法)混合起来。添加一个新的I/O函数,该函数接受一些文件、字符串、blob或其他内容,并返回编码成对象的内容比维护具有处理许多不同I/O操作的许多方法的对象更容易。

1

我建议您通过在项目的pylintrc.pylintrc文件中添加too-many-instance-attributes来完全禁用此消息,示例如下:

[MESSAGES CONTROL]
disable=
    locally-disabled,
    locally-enabled,
    logging-format-interpolation,
    no-init,
    too-few-public-methods,
    too-many-instance-attributes,  # <-- Ensure at least this entry.
    fixme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接