其实我经常好奇一件事, 为什么 Python 得 dict 没有 set 方法, 有人知道什么历史原因吗

1 天前
 iorilu

经常操作 dict

d = {}
d['name'] ='tom'
d['age'] = 30

这样得代码, 其实我很想有一个 set 方法, 我觉得这样 比上面写法更好

而且 dict 明明有 get 方法, 有 set 很合理

而且还有个 setdefault 方法, 而且这个方法很容易混淆, 因为这个方法 主要作用是获取值, 并不是设置值得, 这个名字一看都不清楚什么意思

总的来说, 我认为应该有 set 方法

但 python 一直没有, 而且既然没有, 后面加上应该不会有任何不兼容

当然这么明显得事情 python 开发组不可能不知道, 那么到底是什么原因 不能放一个 set 方法呢

2240 次点击
所在节点    Python
24 条回复
julyclyde
1 天前
set 是 python 语言的关键词
lucasj
1 天前
我也觉得很合理。
cmdOptionKana
1 天前
python 语言本身的设计理念就是想一出是一出,很自由,没啥特殊原因,纯粹当时设计者拍脑袋觉得这样够用,后续也没啥大问题就不改了。
keakon
1 天前
因为有 __setitem__ 方法。提供 dict.get 方法是因为 __getitem__ 在 key 不存在时会抛出异常。
est
1 天前
.update() 啊

LZ 可以了解一下一个叫 UserDict 的东西。
009694
1 天前
get 是为了默认值 set 是为了啥? 因为你 java 先入为主的概念
wxf666
1 天前
不懂就问,`d.set('name', 'tom')` 比 `d['name'] = 'tom'` 好在哪儿呢?

xing7673
1 天前
@wxf666 = 号作为分隔符更清晰
quicknight
1 天前
d.set('name', 'tom'),是把 name 给 tom 还是把 tom 给 name ?
d['name'] = 'tom'这种方式没有这个二义性
Trim21
1 天前
@quicknight 真的会有歧义吗,好奇有哪个 API 设计类似方法的时候把 value 放在前面吗?
quicknight
1 天前
@Trim21 苹果的 OC 和 SWIFT 都是值在前面 KEY 在后面
[dict setObject:@"value" forKey:@"key"]

你如果经常在不同语言中穿梭,或者你只是想看看一个你不懂的语言的逻辑,没有二义性的体验真的好很多
DOLLOR
1 天前
@julyclyde 不是吧? python 里 set 可以作为变量名、函数名用
iorilu
1 天前
@wxf666 get , set 相互匹配

我如果用 get 取值, 然后用 set 赋值不是很合理吗

比如
```
count = p.get('count', 0)
p.set('count', count+1)
```
Soler
1 天前
@iorilu 这个世界本来就是不对等的。

可以使用 p['count'] += 1
deplives
1 天前
我也不知道为啥没有显式的 set ,但是你可以自己实现一个

```python
import ctypes


class PyType(ctypes.Structure):
pass


class PyObject(ctypes.Structure):
Py_ssize_t = (
ctypes.c_int64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_int32
)
_fields_ = [
("ob_refcnt", Py_ssize_t),
("ob_type", ctypes.POINTER(PyType)),
]


class PyTypeObject(PyObject):
_fields_ = [
("dict", ctypes.POINTER(PyObject))
]


def inject(class_, method, force=False):
def _(function):
name_, dict_ = class_.__name__, class_.__dict__
proxy_dict = PyTypeObject.from_address(id(dict_))
namespace = {}
ctypes.pythonapi.PyDict_SetItem(
ctypes.py_object(namespace),
ctypes.py_object(name_),
proxy_dict.dict
)
if not force and namespace.get(name_, {}).get(method, None):
raise RuntimeError(f"已存在方法 {class_.__name__}.{method}()")
namespace[name_][method] = function

return _


@inject(dict, 'set')
def dict_set(d, key, value):
d.update({key: value})
```


a = {}
a.set("name", "hello")
print(a)
Geon97
1 天前
@wxf666 好在没有 d['name'] = 'tom'可读性强
deplives
1 天前
iorilu
1 天前
@Soler 说实话把, 我就是不喜欢方框号操作, 因为我习惯性得觉得方括号就是操作数组类似得东西

主要是我觉得 pyhon 开发组可以加上 set 方法, 至于用不用是开发人员得事, 毕竟还有个 setdefault 呢, 实际上也没啥用, 还不是加上了
Hookery
1 天前
OP 并没有深刻理解 pythonic
iorilu
1 天前
@deplives 好的, 比较底层得方法, 有空学习下

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

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

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

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

© 2021 V2EX