在 lambda 中自动解包的 python3 等效项是什么?

新手上路,请多包涵

考虑以下 python2 代码

In [5]: points = [ (1,2), (2,3)]

In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)

这在 python3 中不受支持,我必须执行以下操作:

 >>> min(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
(1, 2)

这非常丑陋。如果 lambda 是一个函数,我可以做

def some_name_to_think_of(p):
  x, y = p
  return x*x + y*y

在 python3 中删除此功能会强制代码以丑陋的方式(使用魔术索引)或创建不必要的函数(最麻烦的部分是为这些不必要的函数想出好名字)

我认为该功能至少应该单独添加回 lambda。有好的选择吗?


更新: 我正在使用以下助手扩展答案中的想法

def star(f):
  return lambda args: f(*args)

min(points, key=star(lambda x,y: (x*x + y*y))


Update2: 更清洁的版本 star

 import functools

def star(f):
    @functools.wraps(f)
    def f_inner(args):
        return f(*args)
    return f_inner

原文由 balki 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 667
2 个回答

不,没有别的办法。你涵盖了这一切。要走的路是在 Python 思想邮件列表 上提出这个问题,但要准备好在那里争论很多以获得一些牵引力。

实际上,只是不要说“没有出路”,第三种方法可能是实施更多级别的 lambda 调用只是为了展开参数 - 但这会比你的两个建议更加低效和难以阅读:

 min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))


Python 3.8 更新

自 Python 3.8 发布以来,PEP 572(赋值表达式)已作为一种工具提供。

所以,如果有人使用技巧在 lambda 中执行多个表达式——我通常通过创建一个元组并只返回它的最后一个组件来做到这一点,可以执行以下操作:

 >>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
>>> a((3,4))
25

应该记住,这种代码很少会比具有完整功能的代码更具可读性或实用性。尽管如此,还是有可能的用途——如果有各种单行代码可以在这个 point 上运行,那么值得拥有一个 namedtuple ,并使用赋值表达式有效地“将传入序列“投射”到命名元组:

 >>> from collections import namedtuple
>>> point = namedtuple("point", "x y")
>>> b = lambda s: (p:=point(*s), p.x ** 2 + p.y ** 2)[-1]

原文由 jsbueno 发布,翻译遵循 CC BY-SA 4.0 许可协议

根据 http://www.python.org/dev/peps/pep-3113/ tuple unpacking are gone, and 2to3 将像这样翻译它们:

由于单个表达式的限制,lambda 使用元组参数,因此也必须支持它们。这是通过将预期的序列参数绑定到单个参数然后索引该参数来完成的:

lambda (x, y): x + y

将被翻译成:

lambda x_y: x_y[0] + x_y[1]

这与您的实施非常相似。

原文由 njzk2 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题