当前位置:  开发笔记 > 编程语言 > 正文

Dict/Set解析顺序一致性

如何解决《Dict/Set解析顺序一致性》经验,为你挑选了1个好方法。

采用可清洗对象(如dict键或set项目)的容器.因此,字典只能有一个带有值的键1,1.0或者True等等.(注意:有些简化 - 允许哈希冲突,但这些值被认为是相等的)

我的问题是:解析顺序是否定义良好,是否可以跨实现预测结果对象?例如,OSX Python 2.7.11和3.5.1解释dict如下:

>>> { True: 'a', 1: 'b', 1.0: 'c', (1+0j): 'd' }
{True: 'd'}

在这种情况下,似乎保留了第一个键和最后一个值.

类似,在以下情况下set:

>>> { True, 1, 1.0, (1+0j) }
set([(1+0j)])

这里似乎保留了最后一项.

但(如评论中所述):

>>> set([True, 1, 1.0])
set([True])

现在保留了iterable中的第一个.

文档指出项目的顺序(例如in dict.items)是未定义的,但我的问题是指构造 dictset对象的结果.



1> Padraic Cunn..:

现在已经在最近的python版本中修复了这个bug,正如@jsf的回答中所解释的那样

字典显示器

如果给出了逗号分隔的键/数据对序列,则从左到右计算它们以定义字典的条目:每个键对象用作字典中的键以存储相应的数据.这意味着您可以在键/基准列表中多次指定相同的键,并且该键的最终字典值将是给定的最后一个键.

与list和set comprehensions相反,dict理解需要两个用冒号分隔的表达式,后跟通常的"for"和"if"子句.运行理解时,生成的键和值元素将按照生成的顺序插入到新字典中.

设置显示

集合显示产生新的可变集合对象,内容由表达式序列或理解指定.当提供以逗号分隔的表达式列表时,将从左到右计算其元素并将其添加到set对象.当提供理解时,该集合由理解产生的元素构成.

调用set构造函数或使用理解和普通文字有所不同.

def f1():
    return {x for x in [True, 1]}

def f2():
    return set([True, 1])
def f3():
    return {True, 1}
print(f1())
print(f2())
print(f3())
import dis

print("f1")
dis.dis(f1)

print("f2")

dis.dis(f2)

print("f3")
dis.dis(f3)

输出:

{True}
{True}
{1}

如何创建它们会影响结果:

    605           0 LOAD_CONST               1 ( at 0x7fd17dc9a270, file "/home/padraic/Dropbox/python/test.py", line 605>)
              3 LOAD_CONST               2 ('f1..')
              6 MAKE_FUNCTION            0
              9 LOAD_CONST               3 (True)
             12 LOAD_CONST               4 (1)
             15 BUILD_LIST               2
             18 GET_ITER
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 RETURN_VALUE
f2
608           0 LOAD_GLOBAL              0 (set)
              3 LOAD_CONST               1 (True)
              6 LOAD_CONST               2 (1)
              9 BUILD_LIST               2
             12 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             15 RETURN_VALUE
f3
611           0 LOAD_CONST               1 (True)
              3 LOAD_CONST               2 (1)
              6 BUILD_SET                2
              9 RETURN_VALUE

BUILD_SET当您传递由逗号分隔的纯文字时,Python仅运行字节码:

当提供以逗号分隔的表达式列表时,将从左到右计算其元素并将其添加到set对象.

理解线:

当提供理解时,该集合由理解产生的元素构成.

因此,感谢Hamish提交错误报告BUILD_SET,根据Raymond Hettinger在链接中的评论确实归结为操作码.罪魁祸首是Python/ceval.c中的BUILD_SET操作码,它不必要地向后循环,其实现如下:

 TARGET(BUILD_SET) {
            PyObject *set = PySet_New(NULL);
            int err = 0;
            if (set == NULL)
                goto error;
            while (--oparg >= 0) {
                PyObject *item = POP();
                if (err == 0)
                    err = PySet_Add(set, item);
                Py_DECREF(item);
            }
            if (err != 0) {
                Py_DECREF(set);
                goto error;
            }
            PUSH(set);
            DISPATCH();
        }

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有