编码样式-是否有某些原因不总是使用关键字参数?

在开始学习python之前,我先学习了一些Objective-C / Cocoa书籍。 我记得,大多数函数都需要明确声明关键字参数。 直到最近,我都忘记了这一切,只是在Python中使用了位置参数。 但是最近,我遇到了一些由于位置不当而导致的错误-它们是偷偷摸摸的小东西。

让我思考-一般而言,除非有特殊需要非关键字参数的情况-是否有充分的理由不使用关键字参数? 即使对于简单功能也总是使用它们是否被认为是不好的风格?

我感觉就像我的大多数50行程序都定期扩展到500行或更多行一样,如果我习惯于始终使用关键字参数,随着代码的增长,代码将更易于阅读和维护。 有什么原因可能不是这样吗?

更新:

我得到的总体印象是,它具有样式首选项,其中包含许多良好的论点,通常不应将它们用于非常简单的论点,而应与良好的样式保持一致。 在接受之前,我只想澄清-这种方法是否会引起任何特定的非样式问题-例如,性能显着下降?

chris asked 2019-11-08T04:13:56Z
11个解决方案
55 votes

除了代码的清晰性和可读性之外,没有任何理由不使用关键字参数。 是否使用关键字的选择应基于关键字在阅读代码时是否添加其他有用信息。

我遵循以下一般规则:

  1. 如果很难从函数名称中推断出参数的函数(名称),请通过关键字传递它(例如,我不想在代码中包含cls.method(self=cls_instance))。
  2. 如果很难推断出参数的顺序,例如,如果您有太多的参数,或者当您有独立的可选参数时,请通过关键字传递参数(例如,cls.method(self=cls_instance)看起来不太好)。
  3. 如果参数的目的很明显,则不要通过关键字传递前几个参数。 您会看到cls.method(self=cls_instance)self更好,对于plot(x, y, z)也是如此。

在大多数情况下,稳定的强制性参数将是位置参数,而可选参数将是关键字。

在性能上也可能存在差异,因为在每种实现中,关键字参数都会稍慢一些,但是考虑到这通常是过早的优化,其结果并不重要,我认为这对于决定而言并不重要 。

更新:非风格的关注

关键字参数可以完成位置参数可以执行的所有操作,并且,如果要定义新的API,除了可能的性能问题之外,没有技术上的缺点。 但是,如果将代码与现有元素结合在一起,则可能会遇到一些问题。

考虑以下:

  • 如果使函数采用关键字参数,则它将成为接口的一部分。您不能用签名相似但关键字相同的参数来替换函数。
  • 您可能要在函数上使用装饰器或其他实用程序,假定您的函数采用位置参数。 未绑定方法是此类实用程序的一个示例,因为它们在将第一个参数读取为位置后始终将其作为位置传递,因此即使定义中存在参数2404641620213629953,2604601620213629952也无效。

如果您精心设计了API并记录了关键字参数的使用,那么所有这些都不是真正的问题,尤其是如果您不打算设计与现有的东西可以互换的东西时,尤其如此。

Rosh Oxymoron answered 2019-11-08T04:15:23Z
17 votes

如果您考虑提高函数调用的可读性,为什么不简单地将函数声明为普通函数,例如

def test(x, y):
    print "x:", x
    print "y:", y

只需通过显式声明名称来调用函数,如下所示:

test(y=4, x=1)

显然,这将为您提供输出:

x: 1
y: 4

否则此练习将毫无意义。

这样可以避免参数是可选的,也不需要默认值(除非您希望它们为默认值,在这种情况下,请继续使用关键字arguments!:),并为您提供不受顺序限制的命名参数的所有功能和更高的可读性。

bdeniker answered 2019-11-08T04:16:13Z
11 votes

好吧,出于某些原因,我不愿意这样做。

如果所有自变量都是关键字自变量,则这会增加代码中的噪音,并且可能使您不清楚需要哪些自变量和哪些自变量。

另外,如果我必须使用您的代码,我可能想杀死您! (开个玩笑),但是每次都必须键入所有参数的名称……不是那么有趣。

Martin answered 2019-11-08T04:16:50Z
6 votes

我记得在UNIX程序中读过关于“选项”的很好的解释:“选项是可选的,程序应该能够在没有任何选项的情况下运行”。

相同的原理可以应用于Python中的关键字参数。这种类型的参数应允许用户“自定义”函数调用,但是应该可以完全不使用任何隐式的关键字-值参数对来调用函数。

Zaur Nasibov answered 2019-11-08T04:17:21Z
5 votes

为了提供不同的论据,我认为在某些情况下,命名参数可能会提高可读性。 例如,设想一个在系统中创建用户的函数:

create_user("George", "Martin", "g.m@example.com", "payments@example.com", "1", "Radius Circle")

从该定义来看,即使它们都是必需的,也不清楚这些值的含义,但是对于命名参数,它总是显而易见的:

create_user(
    first_name="George",
    last_name="Martin",
    contact_email="g.m@example.com",
    billing_email="payments@example.com",
    street_number="1",
    street_name="Radius Circle")
Brent Newey answered 2019-11-08T04:17:52Z
4 votes

有时候,事情应该很简单,因为它们很简单。

如果始终强制您在每个函数调用上使用关键字参数,那么很快您的代码将变得不可读。

Diego Queiroz answered 2019-11-08T04:18:23Z
4 votes

当Python的内置compile()__import__()函数获得关键字参数支持时,为了简化起见,使用了相同的参数。 如果有的话,似乎对性能没有重大影响。

现在,如果您使函数仅接受关键字参数(而不是允许在调用它们时使用关键字传递位置参数),那么是的,这很烦人。

michel-slm answered 2019-11-08T04:18:54Z
3 votes

当参数的含义很明显时,我看不到使用关键字参数的目的

Xavier Combelle answered 2019-11-08T04:19:19Z
2 votes

当参数列表较长且没有明确定义的顺序时,关键字args是很好的选择(您不容易想出一个清晰的方案来记住); 但是,在许多情况下,使用它们会显得过大或使程序不清楚。

首先,有时记住关键字的顺序比关键字自变量的名称更容易记住,并且指定自变量的名称可能使其不清楚。 从def square_sum(params):中获取square_sum(1,2,3,4,5) # gives 55,并使用以下文档字符串:

randint(low, high=None, size=None)    
Return random integers x such that low <= x < high.
If high is None, then 0 <= x < low.

当我想从[0,10)生成一个随机int时,在我看来比def square_sum(params):更清楚地写square_sum(1,2,3,4,5) # gives 55。 如果您需要以[0,10)生成具有100个数字的数组,则可能可以记住参数顺序并编写square_sum([1,2,3,4,5])。但是,您可能不记得变量名(例如,第一个参数为low,lower,start,min ,最小值),并且一旦必须查找参数名称,就不应该使用它们(因为您只是查找了正确的顺序)。

还应考虑可变参数函数(参数可变的函数本身就是匿名的)。 例如,您可能需要编写类似以下内容的内容:

def square_sum(*params):
    sq_sum = 0
    for p in params:
        sq_sum += p*p
    return sq_sum

可以应用一堆裸参数(square_sum(1,2,3,4,5) # gives 55)。 当然,您可能已经编写了函数以采用可迭代的命名关键字def square_sum(params):,并像square_sum([1,2,3,4,5])那样调用它,但这可能不太直观,尤其是当对参数名称或其内容没有潜在的混淆时。

dr jimbob answered 2019-11-08T04:20:13Z
2 votes

我可以看到的一个缺点是,您必须为所有内容考虑一个合理的默认值,并且在许多情况下,可能没有任何合理的默认值(包括None)。 然后,对于未指定逻辑上应该为位置arg的kwarg的情况,您将不得不编写大量错误处理代码。

想象一下每次写这样的东西..

def logarithm(x=None):
    if x is None:
        raise TypeError("You can't do log(None), sorry!")
wim answered 2019-11-08T04:20:45Z
1 votes

我经常犯的一个错误是,我忘记了在调用函数时必须在任何关键字参数之前指定位置参数。 如果SyntaxError是一个函数,则:

testing(arg = 20, 56)

给出SyntaxError消息; 就像是:

SyntaxError: non-keyword arg after keyword arg

当然很容易修复,这很烦人。 因此,在您提到的几行程序的情况下,在为函数的参数赋予漂亮的描述性名称后,我可能只使用位置参数。 我不知道我所说的是不是一个大问题。

Dora answered 2019-11-08T04:21:25Z
translate from https://stackoverflow.com:/questions/7041752/any-reason-not-to-always-use-keyword-arguments