有理由不总是使用关键字参数吗?
在我开始学习Python之前,我先看了一些关于Objective-C和Cocoa的书。记得大部分函数都需要明确写出关键字参数。直到最近我才意识到这一点,之前一直在Python中只用位置参数。但最近我遇到了一些因为位置不对而导致的bug,真是让人头疼的小问题。
这让我开始思考了——一般来说,除非有特别的情况需要用非关键字参数,是否有理由不使用关键字参数呢?如果总是使用关键字参数,即使是简单的函数,这样算不算不好的风格呢?
我感觉我的程序从50行变成500行甚至更多,如果我习惯性地使用关键字参数,代码在增长时会更容易阅读和维护。有没有什么理由说明这样做不好呢?
更新:
我得到的总体印象是,这主要是个人风格的选择。很多人认为对于非常简单的参数不应该使用关键字参数,但在其他情况下使用它们是符合良好风格的。不过在我接受这个观点之前,我想确认一下——使用这种方法是否会引发一些特定的非风格问题,比如性能显著下降?
11 个回答
嗯,我有几个理由不这样做。
如果你所有的参数都是关键字参数,这样会让代码看起来很乱,而且可能会让人搞不清楚哪些参数是必须的,哪些是可选的。
而且,如果我需要使用你的代码,我可能会想揍你一顿!!(开玩笑的),但是每次都要输入所有参数的名字... 这可真不有趣。
如果你想让函数调用更容易理解,为什么不直接像平常那样声明函数呢,比如:
def test(x, y):
print "x:", x
print "y:", y
然后就可以像这样明确地调用这些函数:
test(y=4, x=1)
这样显然会得到这个输出:
x: 1
y: 4
否则这个练习就没有意义了。
这样做可以避免参数变成可选的,也不需要默认值(当然,如果你想要默认值,那就可以使用关键字参数!:) 这样做可以让你在使用命名参数时更加灵活,且不受顺序的限制,阅读起来也更清晰。
除了代码的清晰度和可读性,没有理由不使用关键字参数。是否使用关键字参数应该根据它是否能在阅读代码时提供额外有用的信息来决定。
我遵循以下一般规则:
- 如果从函数名很难推测出参数的作用,就用关键字传递(例如,我不想在代码中看到
text.splitlines(True)
)。 - 如果很难推测参数的顺序,比如参数太多,或者有独立的可选参数,就用关键字传递(例如
funkyplot(x, y, None, None, None, None, None, None, 'red')
看起来就不太好)。 - 如果参数的目的很明显,就不要用关键字传递前几个参数。比如
sin(2*pi)
比sin(value=2*pi)
更好,plot(x, y, z)
也是一样。
在大多数情况下,稳定的必需参数通常是位置参数,而可选参数则是关键字参数。
还有可能的性能差异,因为在每种实现中,关键字参数会稍微慢一点,但考虑到这通常是过早的优化,结果也不显著,我认为这对决策并不关键。
更新:非风格方面的考虑
关键字参数可以做所有位置参数能做的事情,如果你在定义一个新的API,除了可能的性能问题,没有技术上的缺点。不过,如果你把代码和现有元素结合起来,可能会遇到一些小问题。
考虑以下几点:
- 如果你让你的函数接受关键字参数,这就成了你的接口的一部分。你不能用一个具有相似签名但参数关键字不同的函数来替换你的函数。
- 你可能想在你的函数上使用一个装饰器或其他工具,这些工具假设你的函数接受位置参数。未绑定的方法就是这样的工具的一个例子,因为它们总是将第一个参数作为位置参数传递,所以
cls.method(self=cls_instance)
不管定义中是否有self
参数都无法正常工作。
如果你设计得当并且记录了关键字参数的使用,这些都不会成为真正的问题,尤其是当你设计的东西不需要与现有的东西互换时。