首页 > 解决方案 > 为什么 API 作者会阻止 Python 中的位置参数?

问题描述

使用 tensorflow 实现一些神经网络,我遇到了一个参数引起我注意的方法。我说的是(此处tf.nn.sigmoid_cross_entropy_with_logits的文档)。

它接收的第一个参数作为第一个参数_sentinel=None,根据文档:

_sentinel:用于防止位置参数。内部,请勿使用。

我知道通过使用此参数,必须命名下一个参数而不是位置参数是不是必须使用这个参数,但我的问题是。在哪些情况下防止位置参数有一些好处?他们使用它的主要目标是什么?因为我也可以跑

tf.nn.sigmoid_cross_entropy_with_logits(None, my_labels, my_logits)

都是位置的参数。无论如何,我想澄清一下,我的问题并不集中在 TensorFlow 中,这只是我找到的示例。

标签: python

解决方案


位置参数按照参数的顺序耦合调用者和接收者。它使重构接收器参数的顺序更加困难。

例如,如果我有

def foo(a, b, c):
    do_stuff(a,b,c)

我决定,出于某种原因,也许我想做一个部分功能或其他什么,最好有

def foo(b, a, c):
   do_stuff(a,b,c)

但是现在我在野外有来电者,改变我的合同是非常粗鲁的,所以我被困住了。

Sandi Metz 在Practical Object-Oriented Design in Ruby 中也解决了这个问题。(我知道这是python,但是oop就是oop)

当代码[更改为使用关键字参数]时,它失去了对参数顺序的依赖,但它获得了对[关键字参数]中键名的依赖。这种变化是健康的。新的依赖比旧的更稳定,因此该代码面临被迫更改的风险较小。此外,也许出乎意料的是,[keywords] 提供了一个新的次要好处:散列中的键名提供了关于参数的明确文档。这是使用哈希的副产品,但它是无意的事实使它同样有用。此代码的未来维护者将不胜感激这些信息。

如果您有很多参数,关键字参数也很好。订单很容易出错。在作者看来,它也可能是一个更好的 API。

PEP-3102也解决了这个问题,但我发现从“为什么我会选择设计这样的东西”的角度来看,这个理由并不令人满意

当前的 Python 函数调用范例允许通过位置或关键字指定参数。参数可以通过名称显式填充,也可以通过位置隐式填充。

在某些情况下,函数需要可变数量的参数。Python 语言使用 'varargs' 语法 (*name) 支持这一点,它指定任何“剩余”参数作为元组传递给 varargs 参数。

对此的一个限制是,目前,必须先填充所有常规参数插槽,然后才能填充可变参数插槽。

这并不总是可取的。人们可以很容易地设想一个函数,它接受可变数量的参数,但也接受一个或多个关键字参数形式的“选项”。目前,唯一的方法是同时定义一个可变参数和一个“关键字”参数(**kwargs),然后从字典中手动提取所需的关键字。


推荐阅读