Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 能给我一本同名的字典吗?_Python_Dictionary_Key - Fatal编程技术网

Python 能给我一本同名的字典吗?

Python 能给我一本同名的字典吗?,python,dictionary,key,Python,Dictionary,Key,我需要有一个字典,其中可能有一些键相同的名称,并返回一个值列表时,引用在这种情况下的键 比如说 print mydict['key'] [1,2,3,4,5,6] 为了保持一致性,应该将字典键映射到值列表(或值集),其中一些值可以为空。有一个很好的成语: from collections import defaultdict d = defaultdict(set) d["key"].add(...) (一个defaultdict就像一个普通的字典,但是如果一个键丢失了,它会调用你实例化它

我需要有一个字典,其中可能有一些键相同的名称,并返回一个值列表时,引用在这种情况下的键

比如说

print mydict['key']
[1,2,3,4,5,6]

为了保持一致性,应该将字典键映射到值列表(或值集),其中一些值可以为空。有一个很好的成语:

from collections import defaultdict
d = defaultdict(set)

d["key"].add(...)
(一个
defaultdict
就像一个普通的字典,但是如果一个键丢失了,它会调用你实例化它时传入的参数,并将结果用作默认值。因此,如果你请求一个尚未存在的键,它会自动创建一组空值。)


如果需要使对象看起来更像字典(即通过
d[“key”]=…
设置值),可以执行以下操作但是这可能是个坏主意,因为它违背了正常的Python语法,并且很可能会在以后再次攻击您。特别是如果其他人必须维护您的代码

class Multidict(defaultdict):
    def __init__(self):
        super(Multidict, self).__init__(set)

    def __setitem__(self, key, value):
        if isinstance(value, (self.default_factory)): # self.default_factory is `set`
            super().__setitem__(key, value)
        else:
            self[key].append(value)
我还没有对此进行测试。

您可以使用:

myDict = {'key': []}
然后在运行时:

if newKey in myDict:
    myDict[newKey].append(value)
else:
    myDict[newKey] = [value]
根据@Ben的评论编辑:

myDict = {}
myDict.setdefault(newKey, []).append(value)

您也可以尝试粘贴.util.multidict.multidict

$ easy_install Paste
然后:

像Pylons这样的Web框架使用这个库来处理HTTP查询字符串/post数据,这些数据可以具有相同的名称键

def toMultiDict(items):
    def insertMulti(d, kv):
        k, v = kv
        d.setdefault(k, []).append(v)
        return d
    return reduce(insertMulti, [{}] + items)
应创建从键到值列表的dict:

In [28]: toMultiDict(zip([1,2,1], [4,5,6]))
Out[28]: {1: [4, 6], 2: [5]}

我无法将insertMulti放入lambda,因为lambda需要再次返回dict。

这是使用集合库中的defaultdict对象的理想位置

from collections import defaultdict

mydict = defaultdict(set)
mydict['key'] += set([1,2,3,4])
mydict['key'] += set([4,5,6])

print(mydict['key'])
返回[1,2,3,4,5,6]

在引用未隐式分配的键的情况下,将返回一个空集

print(mydict['bad_key'])
返回[]

在标准库中的dict上使用setdefault将需要在赋值时对语法进行重大更改,并且可能会变得相当混乱。我从未使用过Multidict,但它看起来也像是作业方式的重大改变。使用此方法,您只需假设字典中可能已经有一个与此键关联的值,并在分配键值时使用“+=”运算符稍微修改赋值运算符

仅供参考-我非常喜欢使用NoneType作为默认值,这会导致对无效密钥的任何访问返回None。这在大多数情况下(包括迭代和json转储)都能正常工作,但对于您的特定需要,默认值应为set类型,除非您希望在键中存储重复值。然后使用列表。事实上,任何时候你有一个同质字典,默认的应该是这种类型

mydict = defaultdict(lambda: None)

我对所有建议的解决方案都不满意,所以这是我的解决方案。这是针对Python3的。代码如下

例子 (代码如下)

>a=MultiDict({0:[0]})
>>>a
多目录({0:[0]})
>>>a[0]=(1,7)
>>>a
多目录({0:[1,7]})
>>>a.添加(0,2)
>>>a
多目录({0:[1,7,2]})
>>>a.添加(1、2)
>>>a
多目录({0:[1,7,2],1:[2]})
>>>a.getfirst(0)
1.
>>>a.getfirst(3)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第61行,在getfirst中
文件“”,第17行,在\uu getitem中__
关键错误:3
>>>len(a)
2.
>>>元组(a.items())
((0, [1, 7, 2]), (1, [2]))
>>>元组(a.values())
([1, 7, 2], [2])
>>>a.get(0)
[1, 7, 2]
>>>元组(a.multiitems())
((0, 1), (0, 7), (0, 2), (1, 2))
>>>元组(a.多键())
(0, 0, 0, 1)
>>>元组(a.多值()
(1, 7, 2, 2)
>>>a.删除(0,1)
>>>a
多目录({0:[7,2],1:[2]})
>>>移除(3,5)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第53行,删除
文件“”,第17行,在\uu getitem中__
关键错误:3
>>>a.移除(0,5)
回溯(最近一次呼叫最后一次):
文件“”,第53行,删除
ValueError:list。删除(x):x不在列表中
在处理上述异常期间,发生了另一个异常:
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第56行,删除
ValueError:键0没有值为5的元素
>>>b=MultiDict({0:[7,2],1:[2]})
>>>b==a
真的
>>>c=多指令集(a)
>>>c
多目录({0:[7,2],1:[2]})
>>>d=MultiDict({0:0})
回溯(最近一次呼叫最后一次):
文件“”,第30行,在_init中__
TypeError:“int”对象不可编辑
在处理上述异常期间,发生了另一个异常:
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第33行,在_init中__
TypeError:值必须是iterables,在键0中找到“int”
>>>流行音乐(0)
[7, 2]
>>>a
多目录({1:[2]})
>>>c.项目()
(0, [7, 2])
>>>c.setdefault(0,[1])
[1]
>>>c
多目录({0:[1],1:[2]})
>>>c.setdefault(0,[2])
[1]
>>>c
多目录({0:[1],1:[2]})
>>>c.setdefault(3)
[]
>>>c
多目录({0:[1],1:[2],3:[]))
>>>c.getfirst(3)
回溯(最近一次呼叫最后一次):
文件“”,第61行,在getfirst中
索引器:列表索引超出范围
在处理上述异常期间,发生了另一个异常:
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第63行,在getfirst中
索引器:键3中没有值
>>>c.清除()
>>>c
多目录({})
>>>c.最新情况(b)
>>>c
多目录({0:[7,2],1:[2]})
>>>d=c.复制()
>>>d==c
真的
>>>id(d)==id(c)
假的
>>>来自键的多目录((0,1),[5])
多目录({0:[5],1:[5]})
>>>多指令源键((0,1))
多目录({0:[],1:[]})
代码
试试看:
从collections.abc导入可变映射
除了importorror:#python<3.3
从集合导入可变映射
类MultiDict(可变映射):
@类方法
def fromkeys(cls,seq,value=None,*args,**kwargs):
如果值为“无”:
v=[]
其他:
v=值
返回cls(dict.fromkeys(seq,v,*args,**kwargs))
定义设置项(self、k、v):
自我记录[k]=列表(v)
定义获取项目(self,k):
返回自我。\u dict[k]
定义(自我):
对于k in self.\u dict:
产量k
定义初始化(self,*args,**kwargs):
self._dict=dict(*args,**kwargs)
对于k,v,在self.\u dict.items():
mydict = defaultdict(lambda: None)
>>> a = MultiDict({0: [0]})
>>> a
MultiDict({0: [0]})
>>> a[0] = (1, 7)
>>> a
MultiDict({0: [1, 7]})
>>> a.add(0, 2)
>>> a
MultiDict({0: [1, 7, 2]})
>>> a.add(1, 2)
>>> a
MultiDict({0: [1, 7, 2], 1: [2]})
>>> a.getfirst(0)
1
>>> a.getfirst(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 61, in getfirst
  File "<stdin>", line 17, in __getitem__
KeyError: 3
>>> len(a)
2
>>> tuple(a.items())
((0, [1, 7, 2]), (1, [2]))
>>> tuple(a.values())
([1, 7, 2], [2])
>>> a.get(0)
[1, 7, 2]
>>> tuple(a.multiitems())
((0, 1), (0, 7), (0, 2), (1, 2))
>>> tuple(a.multikeys())
(0, 0, 0, 1)
>>> tuple(a.multivalues())
(1, 7, 2, 2)
>>> a.remove(0, 1)
>>> a
MultiDict({0: [7, 2], 1: [2]})
>>> a.remove(3, 5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 53, in remove
  File "<stdin>", line 17, in __getitem__
KeyError: 3
>>> a.remove(0, 5)
Traceback (most recent call last):
  File "<stdin>", line 53, in remove
ValueError: list.remove(x): x not in list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 56, in remove
ValueError: No element with value 5 for key 0
>>> b = MultiDict({0: [7, 2], 1: [2]})
>>> b == a
True
>>> c = MultiDict(a)
>>> c
MultiDict({0: [7, 2], 1: [2]})
>>> d = MultiDict({0: 0})
Traceback (most recent call last):
  File "<stdin>", line 30, in __init__
TypeError: 'int' object is not iterable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 33, in __init__
TypeError: Values must be iterables, found 'int' for key 0
>>> a.pop(0)
[7, 2]
>>> a
MultiDict({1: [2]})
>>> c.popitem()
(0, [7, 2])
>>> c.setdefault(0, [1])
[1]
>>> c
MultiDict({0: [1], 1: [2]})
>>> c.setdefault(0, [2])
[1]
>>> c
MultiDict({0: [1], 1: [2]})
>>> c.setdefault(3)
[]
>>> c
MultiDict({0: [1], 1: [2], 3: []})
>>> c.getfirst(3)
Traceback (most recent call last):
  File "<stdin>", line 61, in getfirst
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 63, in getfirst
IndexError: No values in key 3
>>> c.clear()
>>> c
MultiDict({})
>>> c.update(b)
>>> c
MultiDict({0: [7, 2], 1: [2]})
>>> d = c.copy()
>>> d == c
True
>>> id(d) == id(c)
False
>>> MultiDict.fromkeys((0, 1), [5])
MultiDict({0: [5], 1: [5]})
>>> MultiDict.fromkeys((0, 1))
MultiDict({0: [], 1: []})
try:
    from collections.abc import MutableMapping
except ImportError:  # python < 3.3
    from collections import MutableMapping

class MultiDict(MutableMapping):
    @classmethod
    def fromkeys(cls, seq, value=None, *args, **kwargs):
        if value is None:
            v = []
        else:
            v = value

        return cls(dict.fromkeys(seq, v, *args, **kwargs))


    def __setitem__(self, k, v):
        self._dict[k] = list(v)


    def __getitem__(self, k):
        return self._dict[k]


    def __iter__(self):
        for k in self._dict:
            yield k


    def __init__(self, *args, **kwargs):
        self._dict = dict(*args, **kwargs)

        for k, v in self._dict.items():
            try:
                self._dict[k] = list(v)
            except TypeError:
                err_str = "Values must be iterables, found '{t}' for key {k}"
                raise TypeError(err_str.format(k=k, t=type(v).__name__))


    def __delitem__(self, k):
        del self._dict[k]


    def __len__(self):
        return len(self._dict)


    def add(self, k, v):
        if not k in self:
            self[k] = []

        self[k].append(v)


    def remove(self, k, v):
        try:
            self[k].remove(v)
        except ValueError:
            err_str = "No element with value {v} for key {k}"
            raise ValueError(err_str.format(v=v, k=k))


    def getfirst(self, k):
        try:
            res = self[k][0]
        except IndexError:
            raise IndexError("No values in key {k}".format(k=k))

        return self[k][0]


    def multiitems(self):
        for k, v in self.items():
            for vv in v:
                yield (k, vv)


    def multikeys(self):
        for k, v in self.items():
            for vv in v:
                yield k


    def multivalues(self):
        for v in self.values():
            for vv in v:
                yield vv


    def setdefault(self, k, default=None):
        if default is None:
            def_val = []
        else:
            def_val = default

        if k not in self:
            self[k] = def_val

        return self[k]


    def copy(self):
        return self.__class__(self)


    def __repr__(self):
        return (
            self.__class__.__name__ + 
            "({{{body}}})".format(body=self._dict)
        )