有什么理由不总是使用关键字参数?

chr*_*ris 58 python coding-style

在进入python之前,我开始使用一些Objective-C/Cocoa书籍.我记得,大多数函数都需要明确说明关键字参数.直到最近我才忘记了这一切,并在Python中使用了位置参数.但是最近,我遇到了一些由不正当的职位造成的错误 - 他们是偷偷摸摸的小东西.

让我思考 - 一般来说,除非有特殊需要非关键字参数的情况 - 有没有什么好的理由不使用关键字参数?即使是简单的功能,它总是被认为是不好的风格吗?

我觉得我的大多数50行程序已经定期扩展到500行或更多行,如果我习惯于总是使用关键字参数,那么随着代码的增长,代码将更易于阅读和维护.这可能不是这样的原因吗?

更新:

我得到的总体印象是它的风格偏好,有许多好的参数,它们通常不应该用于非常简单的参数,但在其他方面与良好的风格一致.在接受之前我只是想澄清一下 - 这种方法是否存在任何特定的非风格问题 - 例如,重要的性能命中?

Ros*_*ron 55

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

我遵循以下一般规则:

  1. 如果很难从函数名称推断出参数的函数(名称) - 用关键字传递它(例如我不想text.splitlines(True)在我的代码中).
  2. 如果很难推断出参数的顺序,例如,如果你有太多的参数,或者你有独立的可选参数 - 通过关键字传递它(例如funkyplot(x, y, None, None, None, None, None, None, 'red')看起来不是特别好).
  3. 如果参数的目的明显,切勿通过关键字传递前几个参数.你看,sin(2*pi)sin(value=2*pi)这更好,同样如此plot(x, y, z).

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

性能上也存在可能的差异,因为在每个实现中,关键字参数会稍微慢一点,但考虑到这通常是一个不成熟的优化,并且它的结果不会很重要,我认为这对决策不重要.

更新:非风格问题

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

考虑以下:

  • 如果使您的函数采用关键字参数,那么它将成为您界面的一部分.您不能将您的函数替换为具有相似签名但同一参数的不同关键字的另一个函数.
  • 您可能希望在函数上使用装饰器或其他实用程序,假定您的函数采用位置参数.未绑定方法是此类实用程序的一个示例,因为它们在将其作为位置读取后始终将第一个参数作为位置传递,因此cls.method(self=cls_instance)即使self定义中存在参数也不起作用.

如果你很好地设计你的API并记录关键字参数的使用,这些都不是真正的问题,特别是如果你没有设计一些可以与已经存在的东西互换的东西.

  • 完美答案.我要补充一点,Python的方式类似于程序命令行选项的传递方式:必需的方法应该是一些,位置,可选的应该作为一个选项(在某种意义上是一个关键字)传递. (10认同)

bde*_*ker 17

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

def test(x, y):
    print "x:", x
    print "y:", y
Run Code Online (Sandbox Code Playgroud)

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

test(y=4, x=1)
Run Code Online (Sandbox Code Playgroud)

这显然给你输出:

x: 1
y: 4
Run Code Online (Sandbox Code Playgroud)

或者这个练习毫无意义.

这避免了参数是可选的并且需要默认值(除非你想要它们,在这种情况下只需要继续使用关键字参数!:)并为你提供所有的多功能性和改进的命令参数的可读性,不受顺序的限制.


Mar*_*tin 11

好吧,有几个原因让我不这样做.

如果你的所有参数都是关键字参数,它会增加代码中的噪音,并且可能会清除哪些参数需要哪些参数以及哪些参数是可选参数.

另外,如果我必须使用你的代码,我可能想杀了你!(开玩笑),但每次都要输入所有参数的名称......不是那么有趣.

  • 我见过一些Smalltalk代码(Obj-C的基础).如果它做得好,它会非常自然地读取.您没有看到参数列表,而是看到一个句子.你必须以不同的方式思考如何命名参数,但是来自Objective-C背景的人可能已经有了这种心态. (3认同)

Bre*_*wey 6

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

create_user("George", "Martin", "g.m@example.com", "payments@example.com", "1", "Radius Circle")
Run Code Online (Sandbox Code Playgroud)

从该定义来看,这些值可能意味着什么并不清楚,即使它们都是必需的,但是对于命名参数,它总是显而易见的:

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")
Run Code Online (Sandbox Code Playgroud)

  • 我认为这取决于功能.在类似于"def validate_email(email)"的情况下,当您查看函数的实例时,它可能很明显. (2认同)

Zau*_*bov 6

我记得在UNIX程序中阅读了一个非常好的"选项"解释:"选项应该是可选的,程序应该能够在没有任何选项的情况下运行".

同样的原则可以应用于Python中的关键字参数.这些参数应该允许用户"自定义"函数调用,但是应该能够在没有任何隐式关键字 - 值参数对的情况下调用函数.

  • @agf你是什么意思? (3认同)
  • `def some_func(x,y,*,method,error ='strict')` - `method`和`error`只能*由关键字指定,而`method`*必须*指定,因为它没有默认值. (3认同)