其实我经常好奇一件事, 为什么 Python 得 dict 没有 set 方法, 有人知道什么历史原因吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
iorilu
V2EX    Python

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

  •  
  •   iorilu 360 天前 3910 次点击
    这是一个创建于 360 天前的主题,其中的信息可能已经有所发展或是发生改变。

    经常操作 dict

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

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

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

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

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

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

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

    27 条回复    2024-10-17 09:26:54 +08:00
    julyclyde
        1
    julyclyde  
       360 天前
    set 是 python 语言的关键词
    lucasj
        2
    lucasj  
       360 天前
    我也觉得很合理。
    cmdOptionKana
        3
    cmdOptionKana  
       360 天前
    python 语言本身的设计理念就是想一出是一出,很自由,没啥特殊原因,纯粹当时设计者拍脑袋觉得这样够用,后续也没啥大问题就不改了。
    keakon
      &nsp; 4
    keakon  
       360 天前
    因为有 __setitem__ 方法。提供 dict.get 方法是因为 __getitem__ 在 key 不存在时会抛出异常。
    est
        5
    est  
       360 天前
    .update() 啊

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

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

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

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

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

    可以使用 p['count'] += 1
    deplives
        15
    deplives  
       360 天前
    我也不知道为啥没有显式的 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
        16
    Geon97  
       360 天前
    @wxf666 好在没有 d['name'] = 'tom'可读性强
    iorilu
        18
    iorilu  
    OP
       360 天前
    @Soler 说实话把, 我就是不喜欢方框号操作, 因为我习惯性得觉得方括号就是操作数组类似得东西

    主要是我觉得 pyhon 开发组可以加上 set 方法, 至于用不用是开发人员得事, 毕竟还有个 setdefault 呢, 实际上也没啥用, 还不是加上了
    Hookery
        19
    Hookery  
       360 天前
    OP 并没有深刻理解 pythonic
    iorilu
        20
    iorilu  
    OP
       360 天前
    @deplives 好的, 比较底层得方法, 有空学习下
    guyeu
        21
    guyeu  
       360 天前
    set 关键字应该是正解,其次应该是 set 的含义在 dict 这个场景并不能很好地表达这个方法的目的。

    dict 是键值对的集合,往集合里添加内容应该是 put 或 insert 。
    julyclyde
        22
    julyclyde  
       360 天前
    @DOLLOR 嗯我错了。不是保留关键词
    是 built-in type
    你如果用 set 做变量名,相当于覆盖了内置的 set 数据类型吧?
    llsquaer
        23
    llsquaer  
       359 天前
    setdefault 是设置默认值,如果有就不设置了。 你用这个取值?防御性编程啊。
    e3c78a97e0f8
        24
    e3c78a97e0f8  
       359 天前
    [Zen of Python:]( https://peps.python.org/pep-0020/)

    There should be one-- and preferably only one --obvious way to do it.

    虽然 Python 开发者自己也经常搞出同一件事的几种做法,但是他们每次都能找到一堆理由。你这个做法完全是 style preference ,并不符合 Zen Of Python 。
    sgld
        25
    sgld  
       358 天前
    d['name'] = 'tom'

    这个本身不就是调用的__setitem__ 嘛,所以为啥还需要再建立一个 set()方法再调这个方法呢?

    存在这个方法才是真正的多此一举吧。就像 6 楼说的,get 方法是因为需要在不存在时返回默认值。否则直接[]取也是一样的。
    sgld
        26
    sgld  
       358 天前
    @iorilu Python 对序列取值就是用的[],你可能只是不习惯而已。就像取属性用的是 . 这个也对应了`__getattr__(self, name)`

    你这单纯不习惯,不同语言有所不同很正常吧
    woodfizky
        27
    woodfizky  
       358 天前
    其实是有类似你说的方法的,但是是 magic method 。

    d['key'] = 'value' 等同于 d.__setitem__('key', 'value')

    字典主要是还有一个 update 方法,实际上就是遍历 key, value 去做__setitem__


    确实有时候会给人一种设计上不一致的感觉:
    value = d['key'] 也就是 value = d.__getitem__('key')
    上面这种方括号用法有 KeyError 的风险,
    d['key'] = 'value' 同样是方括号用法,同样是对应一个魔法方法,这个却不会有问题。
    然后我换一种风格,用 d.get('key') 和 d.update(other_dict), 都不会出现 KeyError 。

    字典 get 方法和__getitem__方法的逻辑并不一样,前者是默认取不到值取默认值,且默认值为 None ;后者取不到值直接报错,且不提供默认值参数。

    不过仔细看看就知道了,get 方法是属于字典这种 python 中的 Mapping 类的,并不是直接对应__getitem__这种魔法方法的。通用类是并没有自带 get 和 set 这种方法的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3983 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 43ms UTC 04:10 PVG 12:10 LAX 21:10 JFK 00:10
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86