考虑以下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
star
import functools def star(f): @functools.wraps(f): def f_inner(args): return f(*args) return f_inner
不,没有其他办法。您覆盖了所有内容。可行的方法是在Python想法邮件列表中提出此问题,但要准备在那儿争论很多以获得更多关注。
实际上,只是不说“没有出路”,第三种方法可能是实现一个更高级别的lambda调用,只是为了展开参数-但这将比您的两个建议效率更高,更难以阅读:
min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))
更新Python 3.8
到目前为止,Python 3.8 alpha1已可用,并且已实现PEP 572赋值表达式。
因此,如果使用技巧在lambda内执行多个表达式-我通常通过创建一个元组并仅返回它的最后一个组件来做到这一点,可以这样做:
>>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1] >>> a((3,4)) 25
应该记住,与具有完整功能相比,这种代码很少会更具可读性或实用性。仍然有可能的用途- 如果有各种各样的单行代码可以对此进行操作point,则值得拥有一个namedtuple,并使用赋值表达式将输入序列有效地“投射”到namedtuple:
point
>>> from collections import namedtuple >>> point = namedtuple("point", "x y") >>> b = lambda s: (p:=point(*s), p.x ** 2 + p.y ** 2)[-1]