Python:避免 Pylint 关于参数过多的警告
我想将一个大的 Python 函数重构为更小的函数。 例如,考虑以下代码片段:
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
当然,这是一个简单的示例。 实际上,代码更为复杂。 我的观点是,它包含许多必须传递给提取的函数的局部范围变量,可能如下所示:
def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
问题是 Pylint 会触发有关参数过多的警告。
我可以通过做类似的事情来避免警告:
def mysum(d):
x1 = d['x1']
x2 = d['x2']
...
x9 = d['x9']
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
def mybigfunction():
...
d = {}
d['x1'] = x1
...
d['x9'] = x9
x = mysum(d)
但这种方法对我来说很难看。 它需要编写大量甚至是冗余的代码。
有更好的方法吗?
I want to refactor a big Python function into smaller ones. For example, consider this following code snippet:
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
Of course, this is a trivial example. In practice, the code is more complex. My point is that it contains many local-scope variables that would have to be passed to the extracted function, which could look like:
def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
The problem is that Pylint would trigger a warning about too many arguments.
I could avoid the warning by doing something like:
def mysum(d):
x1 = d['x1']
x2 = d['x2']
...
x9 = d['x9']
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
def mybigfunction():
...
d = {}
d['x1'] = x1
...
d['x9'] = x9
x = mysum(d)
but this approach loos ugly to me. It requires writing a lot of code that is even redundant.
Is there a better way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
首先,玻璃市的警句之一:
10 个参数中的一些可能是相关的。将它们分组到一个对象中,然后传递它。
举一个例子,因为问题中没有足够的信息来直接回答:
然后你的 10 个参数函数:
变为:
并且调用者更改为:
First, one of Perlis's epigrams:
Some of the 10 arguments are presumably related. Group them into an object, and pass that instead.
Making an example up, because there's not enough information in the question to answer directly:
Then your 10 argument function:
becomes:
and the caller changes to:
您想要一种更好的方式来传递争论,还是只是一种阻止 Pylint 给您带来困难的方法? 如果是后者,您可以通过在代码中添加 Pylint 控制注释来停止烦人的问题:
或者更好的是:
记住尽快将它们重新打开。
在我看来,传递大量参数并没有什么本质上的错误,主张将它们全部包装在某个容器中的解决方案并不能真正解决任何问题,除了阻止 Pylint 打扰你:-) 。
如果您需要传递二十个参数,那么就传递它们。 可能这是必需的,因为您的函数做了太多事情
重构可以在这方面有所帮助,这是你应该关注的。 但这不是我们真正可以做出的决定,除非我们看到“真实”代码是什么。
Do you want a better way to pass the arguments or just a way to stop Pylint from giving you a hard time? If the latter, you can stop the nagging by putting Pylint-controlling comments in your code along the lines of:
or, better:
remembering to turn them back on as soon as practicable.
In my opinion, there's nothing inherently wrong with passing a lot of arguments and solutions advocating wrapping them all up in some container argument don't really solve any problems, other than stopping Pylint from nagging you :-).
If you need to pass twenty arguments, then pass them. It may be that this is required because your function is doing too much
and refactoring could assist there, and that's something you should look at. But it's not a decision we can really make unless we see what the 'real' code is.
您可以轻松更改 Pylint 中允许的最大参数数量。 只需打开您的 pylintrc 文件(如果您还没有文件,请生成它)并将:更改
为:
来自 Pylint 的 手册
You can easily change the maximum allowed number of arguments in Pylint. Just open your pylintrc file (generate it if you don't already have one) and change:
to:
From Pylint's manual
您可以尝试使用 Python 的变量参数 功能:
You could try using Python's variable arguments feature:
也许您可以将一些参数转换为成员变量。 如果你需要那么多的状态,对我来说,上一堂课听起来是个好主意。
Perhaps you could turn some of the arguments into member variables. If you need that much state a class sounds like a good idea to me.
对于 Python 3,您应该只使用 仅关键字参数:
文件 < em>pylint_args_too_many.py
文件pylint_args.py
For Python 3, you should just use keyword-only arguments:
File pylint_args_too_many.py
File pylint_args.py
我不喜欢提及这个数字。 符号名称更具表现力,并且避免添加可能随着时间的推移而过时的注释。
所以我宁愿这样做:
而且我还建议不要让它悬在那里:它将保持活动状态,直到文件结束或被禁用,以先到者为准。
所以最好这样做:
我还建议启用/禁用每行一个警告/错误。
I do not like referring to the number. The symbolic name is much more expressive and avoid having to add a comment that could become obsolete over time.
So I'd rather do:
And I would also recommend to not leave it dangling there: it will stay active until the file ends or it is disabled, whichever comes first.
So better do:
I would also recommend enabling/disabling one single warning/error per line.
简化或分解该函数,使其不需要九个参数(或忽略 Pylint,但像您建议的那样回避会破坏 lint 工具的目的)。
如果这是临时措施,请使用注释禁用有关特定函数的警告,如 Pylint: 为块或语句禁用消息?
稍后,您可以 grep 查找所有禁用的警告。
Simplify or break apart the function so that it doesn't require nine arguments (or ignore Pylint, but dodges like the ones you're proposing defeat the purpose of a lint tool).
If it's a temporary measure, disable the warning for the particular function in question using a comment as described in Pylint: Disable-msg for a block or statement?
Later, you can grep for all of the disabled warnings.
使用 dataclass:
然后
mybigfunction()
返回6
(1+2+3)。这是对你的论点进行分组、组织和记录的好方法。 它还简化了函数的类型提示。
请注意,
dataclass
装饰器所做的一切都是通过实现__init__
方法和其他方法来使您的工作更轻松。Use a dataclass:
Then
mybigfunction()
returns6
(1+2+3).This is a nice way to group, organize, and document your arguments. It also simplifies type hinting of functions.
Note that all the
dataclass
decorator does is making your work easier by implementing the__init__
method and others.Python 有一些不错的函数式编程工具,很可能能很好地满足您的需求。 查看 lambda 函数 和 地图。 另外,当您使用列表似乎会更好时,您正在使用字典。 对于您提供的简单示例,请尝试这个习惯用法。 请注意,地图会更好更快,但可能不适合您的需求:
您提到有很多局部变量,但坦率地说,如果您正在处理列表(或元组),您应该使用列表并分解出所有这些局部变量从长远来看。
Python has some nice functional programming tools that are likely to fit your needs well. Check out lambda functions and map. Also, you're using dicts when it seems like you'd be much better served with lists. For the simple example you provided, try this idiom. Note that map would be better and faster but may not fit your needs:
You mentioned having a lot of local variables, but frankly if you're dealing with lists (or tuples), you should use lists and factor out all those local variables in the long run.
我遇到了同样的烦人错误,我意识到这与一个很酷的功能有关 PyCharm自动检测...只需添加
@staticmethod
装饰器,它就会自动删除使用该方法的错误。I came across the same nagging error, which I realized had something to do with a cool feature PyCharm automatically detects...just add the
@staticmethod
decorator, and it will automatically remove that error where the method is used.