Python lambda 改写

2021-06-23 11:21:43 +08:00
 enderftt

请教各位一个问题,以下代码,怎么用 lambda 改写,我自己尝试写了之后,结果都不对

d = [{'1':1,'2':2},{'3':3,'4':4}]

def t(i):
    i['5']=5
    return i

print(list(map(t,d)))

我自己写的是这个

print(list(map(lambda x:x.update({'5':5}),d)))

update 返回的是 None,所以结果就是[None,None], 不知道各位大佬有其他写法吗?

2696 次点击
所在节点    Python
17 条回复
cyrbuzz
2021-06-23 11:27:35 +08:00
你这个需求直接列表推导不是更香...

[x.update({'5':5}) for x in d]
print(d)
Jirajine
2021-06-23 11:27:44 +08:00
你得用 immutable 的风格写,lambda 返回一个新的对象,而不是修改原本的对象。
ebingtel
2021-06-23 11:31:54 +08:00
lambada 返回一个 tuple,再根据索引 拿到对象
no1xsyzy
2021-06-23 11:41:29 +08:00
immutable 的写法,[{**x, '5': 5} for x in d]
这样 d 完全没有被改动,但因为所有的 dict 都被复制了一份,空间效率可能有点烂,而且还反复 gc,不过考虑到增长也可能重新申请内存大概差距不大(
要么就是 #1,改动完了仍然回头用 d,但如果 d 很长的话这个列表会占空间效率,而且我猜会被 IDE 报『可能没有效果的表达式』,可能可以写成 generator 然后用 itertools 里的东西把整个列表消耗掉( dropwhile 之类)。
nasy
2021-06-23 11:43:40 +08:00
1.
list(map(lambda i: i | {'5': 5}, d))

2.
list(map(lambda i: i.update({'5': 5}) or i, d))

3.
from collection import ChainMap
list(map(lambda i: ChainMap({'5': 5}, i), d))
dongxiao
2021-06-23 11:47:39 +08:00
```
print(list(map(lambda x:x.update({'5':5}) or x,d)))
```
用 update 也没啥问题,比如可以用如上这种 trick 来实现
xuboying
2021-06-23 13:01:35 +08:00
print(list(map(lambda x:{**x, '5':5},d)))
enderftt
2021-06-23 13:07:56 +08:00
@cyrbuzz @Jirajine @ebingtel @no1xsyzy 谢谢 明白了
enderftt
2021-06-23 13:09:29 +08:00
@nasy 这第一种写法 我这里会报错
enderftt
2021-06-23 13:09:40 +08:00
@xuboying 谢谢
enderftt
2021-06-23 13:10:02 +08:00
toaruScar
2021-06-23 13:18:31 +08:00
考虑一下 ChainMap,比 update 快,还会返回东西
https://docs.python.org/3/library/collections.html
wangyzj
2021-06-23 13:31:08 +08:00
print(list(map(lambda x:{**x, '5':5}, [{'1':1,'2':2},{'3':3,'4':4}])))
imn1
2021-06-23 13:36:44 +08:00
关键点是这种 obj.method(x)都是修改 obj 自身,返回 None,所以你要改写就需要返回 obj,而不是 method 的返回

同样有 str.method/list.method 等等

你理清这点,改写的方法就很多了
Contextualist
2021-06-23 14:29:18 +08:00
@enderftt
#5 楼的第一种写法是 Python 3.9 新增的语法

如果要兼容 Python 3.9 以下的版本,个人比较推荐 #4 楼 或 #7 楼的 immutable 写法。
ClericPy
2021-06-23 20:59:37 +08:00
如果你是想要返回点别的... 以前用过类似的, 那种函数返回 None 的设计一开始觉得难受, 后来也能接受

a.update(xxx) or a
print('hello') or result

d = [{'1': 1, '2': 2}, {'3': 3, '4': 4}]


def t(i):
i['5'] = 5
return i


print(list(map(t, d)))
print(list(map(lambda i: i.update({'5': 5}) or i, d)))
# [{'1': 1, '2': 2, '5': 5}, {'3': 3, '4': 4, '5': 5}]
# [{'1': 1, '2': 2, '5': 5}, {'3': 3, '4': 4, '5': 5}]
no1xsyzy
2021-06-23 21:03:47 +08:00
@imn1 这其实是一个语言设计的问题,不过考虑到 Python 的设计是 obj.method 是一个 wrapper,其实是个比较正常的情况。
Ponylang 有 obj.>method(x) 会返回 obj 本身,所以 builder 类的链式调用不需要特地 return 自身,看调用方的代码也直接就清楚这是个对同一对象作各种操作。如果引入了这个语法的话,楼主直接用就成了,既不需要 hack 也不需要强行搞 immutable

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/785258

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX