【问题标题】:Is "*_" an acceptable way to ignore arguments in Python?“*_”是在 Python 中忽略参数的可接受方式吗?
【发布时间】:2022-04-28 00:13:10
【问题描述】:

如果我有一个函数/方法是某个框架的回调实现,并且不关心任何进一步的参数,它似乎在语法上是正确的,并且没有使用 *_ 的 pylint/IDE 投诉表示对任何进一步的论点不感兴趣。我认为的重点是向工具和其他开发人员表达这些论点目前不相关的意图。

澄清我的意思:

def my_callbacK_handler(a, b, *_):
    ...

我没有看到这个成语在野外使用 - 它是否常见,是否有示例,是否存在已知问题?

对于那些不熟悉的人:_ 表达了我对那个符号不感兴趣的意图 - 它是 IDE 和 linter 识别的 Python“虚拟”。

【问题讨论】:

  • 从未见过,当我看到它被提及时不得不暂停,并且不得不阅读你的问题的其余部分弄清楚你的意思。
  • 澄清一下——你说的是类似的东西:def f(a, b, *_) ?
  • 我会使用常规的*args, **kwargs 并在文档字符串中添加注释。
  • 对于您的可选(忽略)参数可能不是很好的形式...使用约定卢克
  • 鉴于_ 是惯用的用于没有意义的名称,因此非常适用。 *dummy,同样。

标签: python


【解决方案1】:

_ 和其他变量一样只是一个变量,但按照惯例,它意味着 您不打算使用该值,只需声明并忘记它。

[OrderedSet() for _ in xrange(n)]

构建n 空有序集的列表。 _ 是索引,但未使用; _ 通常根据需要使用,但未使用的变量名(不仅在 Python 中)。 这只是一个棘手的 Python 习惯用法,因为没有内置语法可以做到这一点。

在其他语言中看到这种情况并不少见(其中_ 是一个有效的标识符)。 _经常 表示一个变量对的值不感兴趣,但它是 出于语法原因需要。

请注意,_(...) 作为宏调用有另一个传统含义,即 来自 gettext,其中使用_("string literal") 表示 需要本地化的字符串。

ActivesState读取的线程

我不能说任何问题,Python内部没有使用它,它只是一个变量,是我们要小心。


关于the syntax of * and ***args**kwargs这两个名字只是约定俗成的,没必要不用。

def my_callbacK_handler(a, b, *_):
    ...

所以,如果我通过_ 成语在您的代码中看到此函数,我的理解是,此函数在其工作中仅使用ab 参数,并且会忽略其他参数。

正如您所说:*_ 表示对任何进一步的争论不感兴趣”

【讨论】:

  • 这更多地解释了_ 的含义,而不是在*_ 成语中的使用位置。一个很好的解释,但没有完全回答预期的问题。
  • 好的,谢谢 Danny,如果我理解正确,请查看更新。我认为使用 *_ 没有任何问题,它只是取决于您看待事物的角度。有时我们在项目中有自己的习语,就是这样。
  • 是的 - 更新是有道理的 - 答案解释了那些不使用 *args 和 **kwargs 或下划线的人,希望其他人清楚“我对任何进一步的论点不感兴趣”的表达阅读本文的编码人员,而不仅仅是 IDE 和 linter。
  • @AdamSmith 如果第 3 方配置为调用这些函数并将传递一些可能使用或忽略的参数,则它可能是有效的。如果被忽略,则使用*_ 可能是有意义的,尽管如果它是如此罕见以至于看起来很奇怪和令人惊讶,那么即使被忽略,也可以说只使用*args 会更好。
  • @AdamSmith 您无法选择禁止调用者传递它们,因为调用者是第三方包,例如 Celery 的 CeleryBeat 部分,它将带有任务元数据的 args 传递给一个函数定义要运行的任务。
【解决方案2】:

*_ 表示多个占位符,就像您编写 def my_callbacK_handler(a, b, _,_,_....,_): 一样,将创建一个名为 _ 的变量,这是一个额外参数的列表

它有两个优点:

  1. 可以处理没有多余参数的情况
def f(): 
   return 1,2,3 

def g(): 
   return 1,2

def h(): 
   return 1,2,3,4

_ 作为占位符只能处理一个值

x,y,_ = g() # ValueError: not enough values to unpack (expected 3, got 2)

x,y,_ = h() # ValueError: too many values to unpack (expected 3)

*_ 可以处理任意数量的值

x,y,*_ = g()                                                                                                                  

print(_)                                                                                                                      
[]

x,y,*_ = h()                                                                                                                  

print(_)                                                                                                                      
[3, 4]

一句话:更喜欢*_以获得更多健壮代码。

【讨论】:

  • _* 是不是搞错了?没有发现任何提及该语法的内容。
【解决方案3】:

让我添加一个例子:

>>> *_, a = [1,2,3]
>>> _, a
([1, 2], 3)


>>> _, a = [1,2,3]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

【讨论】:

    【解决方案4】:

    我相信使用 _ 作为“无关”变量名源自 Prolog。 在 Prolog 中,它不仅意味着您不关心,而且它与其他变量具有不同的语义,因为通常同一变量的两个实例(例如 Dummy)必须匹配相同的值,而 _ 的两个实例可以匹配不同的值。

    当我第一次看到它时,我很惊讶地看到它被用在 Python 中并感到困惑。但它确实有意义,因此 *_ 也是如此。现在我自己用了。

    顺便说一句,似乎 _ 在 Python 中也有特殊的语义,但仅在它被用于 Python shell 的顶层(我认为)的上下文中,其中 _ 自动分配最后一个返回函数值的值。

    【讨论】:

      猜你喜欢
      • 2016-02-17
      • 2013-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      • 2014-01-11
      相关资源
      最近更新 更多