标签归档:tuples

为什么元组在内存中的空间比列表少?

问题:为什么元组在内存中的空间比列表少?

A tuple在Python中占用更少的内存空间:

>>> a = (1,2,3)
>>> a.__sizeof__()
48

lists占用更多的内存空间:

>>> b = [1,2,3]
>>> b.__sizeof__()
64

Python内存管理内部会发生什么?

A tuple takes less memory space in Python:

>>> a = (1,2,3)
>>> a.__sizeof__()
48

whereas lists takes more memory space:

>>> b = [1,2,3]
>>> b.__sizeof__()
64

What happens internally on the Python memory management?


回答 0

我假设您正在使用CPython并使用64位(在CPython 2.7 64位上得到的结果相同)。其他Python实现可能会有所不同,或者您拥有32位Python。

无论采用哪种实现方式,lists都是可变大小的,而tuples是固定大小的。

因此tuples可以将元素直接存储在struct内部,另一方面,列表需要一层间接寻址(它存储指向元素的指针)。间接层是一个指针,在64位系统(即64位,即8字节)上。

但是还有另一件事list:它们过度分配。否则,list.append始终是一项O(n)操作-要使其摊销(快得多!!!),它会过度分配。但是现在它必须跟踪分配的大小和填充的大小(s只需要存储一个大小,因为分配的和填充的大小始终相同)。这意味着每个列表必须存储另一个“大小”,它在64位系统上是64位整数,也是8个字节。O(1)tuple

因此lists比tuples 需要至少16个字节的内存。为什么我说“至少”?由于分配过多。过度分配意味着它分配了比所需更多的空间。但是,过度分配的数量取决于创建列表的“方式”和附加/删除历史记录:

>>> l = [1,2,3]
>>> l.__sizeof__()
64
>>> l.append(4)  # triggers re-allocation (with over-allocation), because the original list is full
>>> l.__sizeof__()
96

>>> l = []
>>> l.__sizeof__()
40
>>> l.append(1)  # re-allocation with over-allocation
>>> l.__sizeof__()
72
>>> l.append(2)  # no re-alloc
>>> l.append(3)  # no re-alloc
>>> l.__sizeof__()
72
>>> l.append(4)  # still has room, so no over-allocation needed (yet)
>>> l.__sizeof__()
72

图片

我决定创建一些图像以伴随以上说明。也许这些有帮助

在示例中,这是(示意性地)将其存储在内存中的方式。我强调了红色(徒手)循环的区别:

这实际上只是一个近似值,因为int对象也是Python对象,并且CPython甚至重用了小整数,因此内存中对象的一种可能更准确的表示形式(尽管不那么可读)将是:

有用的链接:

请注意,__sizeof__它并不会真正返回“正确”的大小!它仅返回存储值的大小。但是,使用sys.getsizeof结果不同:

>>> import sys
>>> l = [1,2,3]
>>> t = (1, 2, 3)
>>> sys.getsizeof(l)
88
>>> sys.getsizeof(t)
72

有24个“额外”字节。这些是真实的,这是方法中未考虑的垃圾收集器开销__sizeof__。这是因为您通常不应该直接使用魔术方法-在这种情况下,请使用知道如何处理魔术方法的函数:(sys.getsizeof这实际上会将GC开销加到的返回值上__sizeof__)。

I assume you’re using CPython and with 64bits (I got the same results on my CPython 2.7 64-bit). There could be differences in other Python implementations or if you have a 32bit Python.

Regardless of the implementation, lists are variable-sized while tuples are fixed-size.

So tuples can store the elements directly inside the struct, lists on the other hand need a layer of indirection (it stores a pointer to the elements). This layer of indirection is a pointer, on 64bit systems that’s 64bit, hence 8bytes.

But there’s another thing that lists do: They over-allocate. Otherwise list.append would be an O(n) operation always – to make it amortized O(1) (much faster!!!) it over-allocates. But now it has to keep track of the allocated size and the filled size (tuples only need to store one size, because allocated and filled size are always identical). That means each list has to store another “size” which on 64bit systems is a 64bit integer, again 8 bytes.

So lists need at least 16 bytes more memory than tuples. Why did I say “at least”? Because of the over-allocation. Over-allocation means it allocates more space than needed. However, the amount of over-allocation depends on “how” you create the list and the append/deletion history:

>>> l = [1,2,3]
>>> l.__sizeof__()
64
>>> l.append(4)  # triggers re-allocation (with over-allocation), because the original list is full
>>> l.__sizeof__()
96

>>> l = []
>>> l.__sizeof__()
40
>>> l.append(1)  # re-allocation with over-allocation
>>> l.__sizeof__()
72
>>> l.append(2)  # no re-alloc
>>> l.append(3)  # no re-alloc
>>> l.__sizeof__()
72
>>> l.append(4)  # still has room, so no over-allocation needed (yet)
>>> l.__sizeof__()
72

Images

I decided to create some images to accompany the explanation above. Maybe these are helpful

This is how it (schematically) is stored in memory in your example. I highlighted the differences with red (free-hand) cycles:

That’s actually just an approximation because int objects are also Python objects and CPython even reuses small integers, so a probably more accurate representation (although not as readable) of the objects in memory would be:

Useful links:

Note that __sizeof__ doesn’t really return the “correct” size! It only returns the size of the stored values. However when you use sys.getsizeof the result is different:

>>> import sys
>>> l = [1,2,3]
>>> t = (1, 2, 3)
>>> sys.getsizeof(l)
88
>>> sys.getsizeof(t)
72

There are 24 “extra” bytes. These are real, that’s the garbage collector overhead that isn’t accounted for in the __sizeof__ method. That’s because you’re generally not supposed to use magic methods directly – use the functions that know how to handle them, in this case: sys.getsizeof (which actually adds the GC overhead to the value returned from __sizeof__).


回答 1

我将更深入地研究CPython代码库,以便我们可以看到大小的实际计算方式。在您的特定示例中没有执行过度分配,因此我不会赘述

我将在这里使用64位值。


lists 的大小由以下函数计算得出list_sizeof

static PyObject *
list_sizeof(PyListObject *self)
{
    Py_ssize_t res;

    res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
    return PyInt_FromSsize_t(res);
}

Py_TYPE(self)是一个抓取ob_typeself(返回PyList_Type),而 _PyObject_SIZE另一种宏抓斗tp_basicsize从该类型。tp_basicsize计算为实例结构sizeof(PyListObject)在哪里PyListObject

PyListObject结构包含三个字段:

PyObject_VAR_HEAD     # 24 bytes 
PyObject **ob_item;   #  8 bytes
Py_ssize_t allocated; #  8 bytes

这些内容有评论(我将它们修剪掉)以解释它们的含义,请点击上面的链接阅读它们。PyObject_VAR_HEAD扩展到3个8字节字段(ob_refcountob_typeob_size),所以一个24字节的贡献。

所以现在res是:

sizeof(PyListObject) + self->allocated * sizeof(void*)

要么:

40 + self->allocated * sizeof(void*)

如果列表实例具有已分配的元素。第二部分计算他们的贡献。self->allocated顾名思义,它保存分配的元素数。

没有任何元素,列表的大小计算为:

>>> [].__sizeof__()
40

即实例结构的大小。


tuple对象没有定义tuple_sizeof函数。而是使用它们object_sizeof来计算大小:

static PyObject *
object_sizeof(PyObject *self, PyObject *args)
{
    Py_ssize_t res, isize;

    res = 0;
    isize = self->ob_type->tp_itemsize;
    if (isize > 0)
        res = Py_SIZE(self) * isize;
    res += self->ob_type->tp_basicsize;

    return PyInt_FromSsize_t(res);
}

lists一样,它获取tp_basicsize和,如果对象具有非零值tp_itemsize(意味着它具有可变长度的实例),它将乘以元组中的项数(通过Py_SIZEtp_itemsize

tp_basicsize再次使用sizeof(PyTupleObject)其中的 PyTupleObject结构包含

PyObject_VAR_HEAD       # 24 bytes 
PyObject *ob_item[1];   # 8  bytes

因此,没有任何元素(即Py_SIZEreturn 0),空元组的大小等于sizeof(PyTupleObject)

>>> ().__sizeof__()
24

?? 嗯,这里是我还没有找到一个解释,一个古怪tp_basicsizetuples的实际计算公式如下:

sizeof(PyTupleObject) - sizeof(PyObject *)

为什么8要从中删除其他字节tp_basicsize是我一直无法找到的。(有关可能的解释,请参阅MSeifert的评论)


但是,这基本上是您特定示例中的区别list还会保留许多已分配的元素,这有助于确定何时再次过度分配。

现在,当添加其他元素时,列表确实会执行此过度分配以实现O(1)追加。由于MSeifert的封面很好地覆盖了他的答案,因此尺寸更大。

I’ll take a deeper dive into the CPython codebase so we can see how the sizes are actually calculated. In your specific example, no over-allocations have been performed, so I won’t touch on that.

I’m going to use 64-bit values here, as you are.


The size for lists is calculated from the following function, list_sizeof:

static PyObject *
list_sizeof(PyListObject *self)
{
    Py_ssize_t res;

    res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
    return PyInt_FromSsize_t(res);
}

Here Py_TYPE(self) is a macro that grabs the ob_type of self (returning PyList_Type) while _PyObject_SIZE is another macro that grabs tp_basicsize from that type. tp_basicsize is calculated as sizeof(PyListObject) where PyListObject is the instance struct.

The PyListObject structure has three fields:

PyObject_VAR_HEAD     # 24 bytes 
PyObject **ob_item;   #  8 bytes
Py_ssize_t allocated; #  8 bytes

these have comments (which I trimmed) explaining what they are, follow the link above to read them. PyObject_VAR_HEAD expands into three 8 byte fields (ob_refcount, ob_type and ob_size) so a 24 byte contribution.

So for now res is:

sizeof(PyListObject) + self->allocated * sizeof(void*)

or:

40 + self->allocated * sizeof(void*)

If the list instance has elements that are allocated. the second part calculates their contribution. self->allocated, as it’s name implies, holds the number of allocated elements.

Without any elements, the size of lists is calculated to be:

>>> [].__sizeof__()
40

i.e the size of the instance struct.


tuple objects don’t define a tuple_sizeof function. Instead, they use object_sizeof to calculate their size:

static PyObject *
object_sizeof(PyObject *self, PyObject *args)
{
    Py_ssize_t res, isize;

    res = 0;
    isize = self->ob_type->tp_itemsize;
    if (isize > 0)
        res = Py_SIZE(self) * isize;
    res += self->ob_type->tp_basicsize;

    return PyInt_FromSsize_t(res);
}

This, as for lists, grabs the tp_basicsize and, if the object has a non-zero tp_itemsize (meaning it has variable-length instances), it multiplies the number of items in the tuple (which it gets via Py_SIZE) with tp_itemsize.

tp_basicsize again uses sizeof(PyTupleObject) where the PyTupleObject struct contains:

PyObject_VAR_HEAD       # 24 bytes 
PyObject *ob_item[1];   # 8  bytes

So, without any elements (that is, Py_SIZE returns 0) the size of empty tuples is equal to sizeof(PyTupleObject):

>>> ().__sizeof__()
24

huh? Well, here’s an oddity which I haven’t found an explanation for, the tp_basicsize of tuples is actually calculated as follows:

sizeof(PyTupleObject) - sizeof(PyObject *)

why an additional 8 bytes is removed from tp_basicsize is something I haven’t been able to find out. (See MSeifert’s comment for a possible explanation)


But, this is basically the difference in your specific example. lists also keep around a number of allocated elements which helps determine when to over-allocate again.

Now, when additional elements are added, lists do indeed perform this over-allocation in order to achieve O(1) appends. This results in greater sizes as MSeifert’s covers nicely in his answer.


回答 2

MSeifert的答案涵盖了广泛的范围;为简单起见,您可以想到:

tuple是一成不变的。一旦设置,您将无法更改。因此,您预先知道需要为该对象分配多少内存。

list易变。您可以在其中添加或删除项目。它必须知道它的大小(用于内部隐含)。根据需要调整大小。

没有免费的餐点 -这些功能需要付费。因此,列表的内存开销。

MSeifert answer covers it broadly; to keep it simple you can think of:

tuple is immutable. Once it set, you can’t change it. So you know in advance how much memory you need to allocate for that object.

list is mutable. You can add or remove items to or from it. It has to know the size of it (for internal impl.). It resizes as needed.

There are no free meals – these capabilities comes with a cost. Hence the overhead in memory for lists.


回答 3

元组的大小是有前缀的,这意味着在元组初始化时,解释器会为所包含的数据分配足够的空间,这就是它的结尾,使其具有不变性(无法修改),而列表是可变对象,因此意味着动态分配内存,因此避免每次您追加或修改列表时都要分配空间(分配足够的空间来容纳已更改的数据并将数据复制到其中),它会为以后的追加,修改等分配更多的空间。总结。

The size of the tuple is prefixed, meaning at tuple initialization the interpreter allocate enough space for the contained data, and that’s the end of it, giving it’s immutable (can’t be modified), whereas a list is a mutable object hence implying dynamic allocation of memory, so to avoid allocating space each time you append or modify the list ( allocate enough space to contain the changed data and copy the data to it), it allocates additional space for future append, modifications, … that pretty much sums it up.


如何将元组列表转换为多个列表?

问题:如何将元组列表转换为多个列表?

假设我有一个元组列表,并且我想转换为多个列表。

例如,元组列表是

[(1,2),(3,4),(5,6),]

Python中是否有任何内置函数可以将其转换为:

[1,3,5],[2,4,6]

这可以是一个简单的程序。但是我只是对Python中存在这种内置函数感到好奇。

Suppose I have a list of tuples and I want to convert to multiple lists.

For example, the list of tuples is

[(1,2),(3,4),(5,6),]

Is there any built-in function in Python that convert it to:

[1,3,5],[2,4,6]

This can be a simple program. But I am just curious about the existence of such built-in function in Python.


回答 0

内置功能zip()几乎可以满足您的需求:

>>> zip(*[(1, 2), (3, 4), (5, 6)])
[(1, 3, 5), (2, 4, 6)]

唯一的区别是您得到元组而不是列表。您可以使用将它们转换为列表

map(list, zip(*[(1, 2), (3, 4), (5, 6)]))

The built-in function zip() will almost do what you want:

>>> zip(*[(1, 2), (3, 4), (5, 6)])
[(1, 3, 5), (2, 4, 6)]

The only difference is that you get tuples instead of lists. You can convert them to lists using

map(list, zip(*[(1, 2), (3, 4), (5, 6)]))

回答 1

python docs

zip()与*运算符结合可用于解压缩列表:

具体的例子:

>>> zip((1,3,5),(2,4,6))
[(1, 2), (3, 4), (5, 6)]
>>> zip(*[(1, 2), (3, 4), (5, 6)])
[(1, 3, 5), (2, 4, 6)]

或者,如果您确实想要列表:

>>> map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
[[1, 3, 5], [2, 4, 6]]

From the python docs:

zip() in conjunction with the * operator can be used to unzip a list:

Specific example:

>>> zip((1,3,5),(2,4,6))
[(1, 2), (3, 4), (5, 6)]
>>> zip(*[(1, 2), (3, 4), (5, 6)])
[(1, 3, 5), (2, 4, 6)]

Or, if you really want lists:

>>> map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
[[1, 3, 5], [2, 4, 6]]

回答 2

用:

a = [(1,2),(3,4),(5,6),]    
b = zip(*a)
>>> [(1, 3, 5), (2, 4, 6)]

Use:

a = [(1,2),(3,4),(5,6),]    
b = zip(*a)
>>> [(1, 3, 5), (2, 4, 6)]

回答 3

franklsf95在回答中选择了性能,因此选择list.append(),但是它们并不是最佳的。

添加列表理解后,我得到以下结果:

def t1(zs):
    xs, ys = zip(*zs)
    return xs, ys

def t2(zs):
    xs, ys = [], []
    for x, y in zs:
        xs.append(x)
        ys.append(y)
    return xs, ys

def t3(zs):
    xs, ys = [x for x, y in zs], [y for x, y in zs]
    return xs, ys

if __name__ == '__main__':
    from timeit import timeit
    setup_string='''\
N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))
from __main__ import t1, t2, t3
'''
    print(f'zip:\t\t{timeit('t1(zs)', setup=setup_string, number=1000)}')
    print(f'append:\t\t{timeit('t2(zs)', setup=setup_string, number=1000)}')
    print(f'list comp:\t{timeit('t3(zs)', setup=setup_string, number=1000)}')

结果如下:

zip:            122.11585397789766
append:         356.44876132614047
list comp:      144.637765085659

因此,如果您追求性能,那么zip()尽管列表理解并不太落后,但您可能应该使用。append相比较而言,的效果实际上很差。

franklsf95 goes for performance in his answer and opts for list.append(), but they are not optimal.

Adding list comprehensions, I ended up with the following:

def t1(zs):
    xs, ys = zip(*zs)
    return xs, ys

def t2(zs):
    xs, ys = [], []
    for x, y in zs:
        xs.append(x)
        ys.append(y)
    return xs, ys

def t3(zs):
    xs, ys = [x for x, y in zs], [y for x, y in zs]
    return xs, ys

if __name__ == '__main__':
    from timeit import timeit
    setup_string='''\
N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))
from __main__ import t1, t2, t3
'''
    print(f'zip:\t\t{timeit('t1(zs)', setup=setup_string, number=1000)}')
    print(f'append:\t\t{timeit('t2(zs)', setup=setup_string, number=1000)}')
    print(f'list comp:\t{timeit('t3(zs)', setup=setup_string, number=1000)}')

This gave the result:

zip:            122.11585397789766
append:         356.44876132614047
list comp:      144.637765085659

So if you are after performance, you should probably use zip() although list comprehensions are not too far behind. The performance of append is actually pretty poor in comparison.


回答 4

尽管使用的*zip是Pythonic,但以下代码具有更好的性能:

xs, ys = [], []
for x, y in zs:
    xs.append(x)
    ys.append(y)

同样,当原始列表zs为空时,*zip将引发,但是此代码可以正确处理。

我只是进行了一个快速实验,结果如下:

Using *zip:     1.54701614s
Using append:   0.52687597s

多次运行,append比运行速度快3到4倍zip!测试脚本在这里:

#!/usr/bin/env python3
import time

N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))

t1 = time.time()

xs_, ys_ = zip(*zs)
print(len(xs_), len(ys_))

t2 = time.time()

xs_, ys_ = [], []
for x, y in zs:
    xs_.append(x)
    ys_.append(y)
print(len(xs_), len(ys_))

t3 = time.time()

print('Using *zip:\t{:.8f}s'.format(t2 - t1))
print('Using append:\t{:.8f}s'.format(t3 - t2))

我的Python版本:

Python 3.6.3 (default, Oct 24 2017, 12:18:40)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

Despite *zip being more Pythonic, the following code has much better performance:

xs, ys = [], []
for x, y in zs:
    xs.append(x)
    ys.append(y)

Also, when the original list zs is empty, *zip will raise, but this code can properly handle.

I just ran a quick experiment, and here is the result:

Using *zip:     1.54701614s
Using append:   0.52687597s

Running it multiple times, append is 3x – 4x faster than zip! The test script is here:

#!/usr/bin/env python3
import time

N = 2000000
xs = list(range(1, N))
ys = list(range(N+1, N*2))
zs = list(zip(xs, ys))

t1 = time.time()

xs_, ys_ = zip(*zs)
print(len(xs_), len(ys_))

t2 = time.time()

xs_, ys_ = [], []
for x, y in zs:
    xs_.append(x)
    ys_.append(y)
print(len(xs_), len(ys_))

t3 = time.time()

print('Using *zip:\t{:.8f}s'.format(t2 - t1))
print('Using append:\t{:.8f}s'.format(t3 - t2))

My Python Version:

Python 3.6.3 (default, Oct 24 2017, 12:18:40)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

回答 5

除了Claudiu的答案,您还可以使用:

>>>a, b = map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
>>>a
[1,3,5]
>>>b
[2,4,6]

根据@Peyman mohseni kiasari编辑

In addition to Claudiu’s answer, you can use:

>>>a, b = map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
>>>a
[1,3,5]
>>>b
[2,4,6]

Edited according to @Peyman mohseni kiasari


回答 6

添加到Claudiu和Claudiu的答案中,并且由于需要在python 3中从itertools导入map,因此您还可以使用以下列表推导:

[[*x] for x in zip(*[(1,2),(3,4),(5,6)])]
>>> [[1, 3, 5], [2, 4, 6]]

Adding to Claudiu’s and Claudiu’s answer and since map needs to be imported from itertools in python 3, you also use a list comprehension like:

[[*x] for x in zip(*[(1,2),(3,4),(5,6)])]
>>> [[1, 3, 5], [2, 4, 6]]

Python:将元组/字典作为键,进行选择,排序

问题:Python:将元组/字典作为键,进行选择,排序

假设我有大量不同颜色的水果,例如24个蓝色香蕉,12个绿色苹果,0个蓝色草莓等等。我想将它们组织成Python的数据结构,以便于选择和排序。我的想法是将它们放入以元组为键的字典中,例如,

{ ('banana',    'blue' ): 24,
  ('apple',     'green'): 12,
  ('strawberry','blue' ): 0,
  ...
}

甚至字典,例如

{ {'fruit': 'banana',    'color': 'blue' }: 24,
  {'fruit': 'apple',     'color': 'green'}: 12,
  {'fruit': 'strawberry','color': 'blue' }: 0,
  ...
}

例如,我想检索所有蓝色水果或所有颜色的香蕉的列表,或按水果名称对这本词典进行排序。有没有办法做到这一点?

用元组作为键的字典可能不是处理这种情况的正确方法。

欢迎所有建议!

Suppose I have quantities of fruits of different colors, e.g., 24 blue bananas, 12 green apples, 0 blue strawberries and so on. I’d like to organize them in a data structure in Python that allows for easy selection and sorting. My idea was to put them into a dictionary with tuples as keys, e.g.,

{
    ('banana',    'blue' ): 24,
    ('apple',     'green'): 12,
    ('strawberry','blue' ): 0,
    # ...
}

or even dictionaries, e.g.,

{
    {'fruit': 'banana',    'color': 'blue' }: 24,
    {'fruit': 'apple',     'color': 'green'}: 12,
    {'fruit': 'strawberry','color': 'blue' }: 0,
    # ...
}

I’d like to retrieve a list of all blue fruit, or bananas of all colors, for example, or to sort this dictionary by the name of the fruit. Are there ways to do this in a clean way?

It might well be that dictionaries with tuples as keys are not the proper way to handle this situation.

All suggestions welcome!


回答 0

就个人而言,我喜欢python的一件事是tuple-dict组合。您在这里拥有的实际上是一个2d数组(其中x =水果名称,y =颜色),而且我通常是实现2d数组的元组字典的支持者,至少在诸如之类numpy的数据库不适合使用时。简而言之,我认为您有一个很好的方法。

请注意,如果不做一些额外的工作,就不能将字典用作字典中的键,因此这不是一个很好的解决方案。

也就是说,您还应该考虑namedtuple()。这样,您可以执行以下操作:

>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", ["name", "color"])
>>> f = Fruit(name="banana", color="red")
>>> print f
Fruit(name='banana', color='red')
>>> f.name
'banana'
>>> f.color
'red'

现在您可以使用fruitcount字典:

>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5

其他技巧:

>>> fruits = fruitcount.keys()
>>> fruits.sort()
>>> print fruits
[Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red'), 
 Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue')]
>>> fruits.sort(key=lambda x:x.color)
>>> print fruits
[Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue'), 
 Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red')]

与chmullig相呼应,要获得一个水果的所有颜色的列表,您必须过滤键,即

bananas = [fruit for fruit in fruits if fruit.name=='banana']

Personally, one of the things I love about python is the tuple-dict combination. What you have here is effectively a 2d array (where x = fruit name and y = color), and I am generally a supporter of the dict of tuples for implementing 2d arrays, at least when something like numpy or a database isn’t more appropriate. So in short, I think you’ve got a good approach.

Note that you can’t use dicts as keys in a dict without doing some extra work, so that’s not a very good solution.

That said, you should also consider namedtuple(). That way you could do this:

>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", ["name", "color"])
>>> f = Fruit(name="banana", color="red")
>>> print f
Fruit(name='banana', color='red')
>>> f.name
'banana'
>>> f.color
'red'

Now you can use your fruitcount dict:

>>> fruitcount = {Fruit("banana", "red"):5}
>>> fruitcount[f]
5

Other tricks:

>>> fruits = fruitcount.keys()
>>> fruits.sort()
>>> print fruits
[Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red'), 
 Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue')]
>>> fruits.sort(key=lambda x:x.color)
>>> print fruits
[Fruit(name='banana', color='blue'), 
 Fruit(name='strawberry', color='blue'), 
 Fruit(name='apple', color='green'), 
 Fruit(name='apple', color='red')]

Echoing chmullig, to get a list of all colors of one fruit, you would have to filter the keys, i.e.

bananas = [fruit for fruit in fruits if fruit.name=='banana']

回答 1

最好的选择是创建一个简单的数据结构来对您所拥有的进行建模。然后,您可以将这些对象存储在一个简单的列表中,并根据需要进行排序/检索。

对于这种情况,我将使用以下类:

class Fruit:
    def __init__(self, name, color, quantity): 
        self.name = name
        self.color = color
        self.quantity = quantity

    def __str__(self):
        return "Name: %s, Color: %s, Quantity: %s" % \
     (self.name, self.color, self.quantity)

然后,您可以简单地构造“ Fruit”实例并将其添加到列表中,如下所示:

fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1] 

简单的列表fruits将更加容易,混乱并且维护得更好。

一些使用示例:

下面的所有输出是运行给定代码段后的结果:

for fruit in fruits:
    print fruit

未排序清单:

显示:

Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12

按名称按字母顺序排序:

fruits.sort(key=lambda x: x.name.lower())

显示:

Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22

按数量排序:

fruits.sort(key=lambda x: x.quantity)

显示:

Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32

颜色==红色:

red_fruit = filter(lambda f: f.color == "red", fruits)

显示:

Name: apple, Color: red, Quantity: 12

Your best option will be to create a simple data structure to model what you have. Then you can store these objects in a simple list and sort/retrieve them any way you wish.

For this case, I’d use the following class:

class Fruit:
    def __init__(self, name, color, quantity): 
        self.name = name
        self.color = color
        self.quantity = quantity

    def __str__(self):
        return "Name: %s, Color: %s, Quantity: %s" % \
     (self.name, self.color, self.quantity)

Then you can simply construct “Fruit” instances and add them to a list, as shown in the following manner:

fruit1 = Fruit("apple", "red", 12)
fruit2 = Fruit("pear", "green", 22)
fruit3 = Fruit("banana", "yellow", 32)
fruits = [fruit3, fruit2, fruit1] 

The simple list fruits will be much easier, less confusing, and better-maintained.

Some examples of use:

All outputs below is the result after running the given code snippet followed by:

for fruit in fruits:
    print fruit

Unsorted list:

Displays:

Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22
Name: apple, Color: red, Quantity: 12

Sorted alphabetically by name:

fruits.sort(key=lambda x: x.name.lower())

Displays:

Name: apple, Color: red, Quantity: 12
Name: banana, Color: yellow, Quantity: 32
Name: pear, Color: green, Quantity: 22

Sorted by quantity:

fruits.sort(key=lambda x: x.quantity)

Displays:

Name: apple, Color: red, Quantity: 12
Name: pear, Color: green, Quantity: 22
Name: banana, Color: yellow, Quantity: 32

Where color == red:

red_fruit = filter(lambda f: f.color == "red", fruits)

Displays:

Name: apple, Color: red, Quantity: 12

回答 2

数据库,词典的字典,词典列表的字典,命名为tuple(这是一个子类),sqlite,冗余…我不敢相信自己的眼睛。还有什么 ?

“很可能以元组为键的字典不是处理这种情况的正确方法。”

“我的直觉是数据库对于OP的需求而言是过大的;”

是的 我想

因此,我认为,一个元组列表就足够了:

from operator import itemgetter

li = [  ('banana',     'blue'   , 24) ,
        ('apple',      'green'  , 12) ,
        ('strawberry', 'blue'   , 16 ) ,
        ('banana',     'yellow' , 13) ,
        ('apple',      'gold'   , 3 ) ,
        ('pear',       'yellow' , 10) ,
        ('strawberry', 'orange' , 27) ,
        ('apple',      'blue'   , 21) ,
        ('apple',      'silver' , 0 ) ,
        ('strawberry', 'green'  , 4 ) ,
        ('banana',     'brown'  , 14) ,
        ('strawberry', 'yellow' , 31) ,
        ('apple',      'pink'   , 9 ) ,
        ('strawberry', 'gold'   , 0 ) ,
        ('pear',       'gold'   , 66) ,
        ('apple',      'yellow' , 9 ) ,
        ('pear',       'brown'  , 5 ) ,
        ('strawberry', 'pink'   , 8 ) ,
        ('apple',      'purple' , 7 ) ,
        ('pear',       'blue'   , 51) ,
        ('chesnut',    'yellow',  0 )   ]


print set( u[1] for u in li ),': all potential colors'
print set( c for f,c,n in li if n!=0),': all effective colors'
print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'
print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'
print

print set( u[0] for u in li ),': all potential fruits'
print set( f for f,c,n in li if n!=0),': all effective fruits'
print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'
print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'
print

print len(set( u[1] for u in li )),': number of all potential colors'
print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'
print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'
print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'
print

# sorting li by name of fruit
print sorted(li),'  sorted li by name of fruit'
print

# sorting li by number 
print sorted(li, key = itemgetter(2)),'  sorted li by number'
print

# sorting li first by name of color and secondly by name of fruit
print sorted(li, key = itemgetter(1,0)),'  sorted li first by name of color and secondly by name of fruit'
print

结果

set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colors
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors
['blue', 'yellow', 'brown'] : all potential colors of bananas
['blue', 'yellow', 'brown'] : all effective colors of bananas

set(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruits
set(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits
['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow
['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow

9 : number of all potential colors
8 : number of all effective colors
6 : number of potential colors of strawberry
5 : number of effective colors of strawberry

[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)]   sorted li by name of fruit

[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)]   sorted li by number

[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)]   sorted li first by name of color and secondly by name of fruit

Database, dict of dicts, dictionary of list of dictionaries, named tuple (it’s a subclass), sqlite, redundancy… I didn’t believe my eyes. What else ?

“It might well be that dictionaries with tuples as keys are not the proper way to handle this situation.”

“my gut feeling is that a database is overkill for the OP’s needs; “

Yeah! I thought

So, in my opinion, a list of tuples is plenty enough :

from operator import itemgetter

li = [  ('banana',     'blue'   , 24) ,
        ('apple',      'green'  , 12) ,
        ('strawberry', 'blue'   , 16 ) ,
        ('banana',     'yellow' , 13) ,
        ('apple',      'gold'   , 3 ) ,
        ('pear',       'yellow' , 10) ,
        ('strawberry', 'orange' , 27) ,
        ('apple',      'blue'   , 21) ,
        ('apple',      'silver' , 0 ) ,
        ('strawberry', 'green'  , 4 ) ,
        ('banana',     'brown'  , 14) ,
        ('strawberry', 'yellow' , 31) ,
        ('apple',      'pink'   , 9 ) ,
        ('strawberry', 'gold'   , 0 ) ,
        ('pear',       'gold'   , 66) ,
        ('apple',      'yellow' , 9 ) ,
        ('pear',       'brown'  , 5 ) ,
        ('strawberry', 'pink'   , 8 ) ,
        ('apple',      'purple' , 7 ) ,
        ('pear',       'blue'   , 51) ,
        ('chesnut',    'yellow',  0 )   ]


print set( u[1] for u in li ),': all potential colors'
print set( c for f,c,n in li if n!=0),': all effective colors'
print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'
print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'
print

print set( u[0] for u in li ),': all potential fruits'
print set( f for f,c,n in li if n!=0),': all effective fruits'
print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'
print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'
print

print len(set( u[1] for u in li )),': number of all potential colors'
print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'
print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'
print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'
print

# sorting li by name of fruit
print sorted(li),'  sorted li by name of fruit'
print

# sorting li by number 
print sorted(li, key = itemgetter(2)),'  sorted li by number'
print

# sorting li first by name of color and secondly by name of fruit
print sorted(li, key = itemgetter(1,0)),'  sorted li first by name of color and secondly by name of fruit'
print

result

set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colors
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors
['blue', 'yellow', 'brown'] : all potential colors of bananas
['blue', 'yellow', 'brown'] : all effective colors of bananas

set(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruits
set(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits
['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow
['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow

9 : number of all potential colors
8 : number of all effective colors
6 : number of potential colors of strawberry
5 : number of effective colors of strawberry

[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)]   sorted li by name of fruit

[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)]   sorted li by number

[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)]   sorted li first by name of color and secondly by name of fruit

回答 3

在这种情况下,字典可能不是您应该使用的字典。功能更全的库将是更好的选择。可能是真实的数据库。最简单的是sqlite。您可以通过传递字符串’:memory:’而不是文件名来将整个内容保留在内存中。

如果您确实想继续沿着这条路径前进,则可以使用键或值中的额外属性来完成。但是,字典不能是另一本字典的键,而元组可以。该文档说明了允许的内容。它必须是一个不可变的对象,其中包括仅包含字符串和数字的字符串,数字和元组(以及递归仅包含那些类型的更多元组…)。

您可以使用做第一个示例d = {('apple', 'red') : 4},但是要查询所需的内容将非常困难。您需要执行以下操作:

#find all apples
apples = [d[key] for key in d.keys() if key[0] == 'apple']

#find all red items
red = [d[key] for key in d.keys() if key[1] == 'red']

#the red apple
redapples = d[('apple', 'red')]

A dictionary probably isn’t what you should be using in this case. A more full featured library would be a better alternative. Probably a real database. The easiest would be sqlite. You can keep the whole thing in memory by passing in the string ‘:memory:’ instead of a filename.

If you do want to continue down this path, you can do it with the extra attributes in the key or the value. However a dictionary can’t be the key to a another dictionary, but a tuple can. The docs explain what’s allowable. It must be an immutable object, which includes strings, numbers and tuples that contain only strings and numbers (and more tuples containing only those types recursively…).

You could do your first example with d = {('apple', 'red') : 4}, but it’ll be very hard to query for what you want. You’d need to do something like this:

#find all apples
apples = [d[key] for key in d.keys() if key[0] == 'apple']

#find all red items
red = [d[key] for key in d.keys() if key[1] == 'red']

#the red apple
redapples = d[('apple', 'red')]

回答 4

使用键作为元组时,只需使用给定的第二个组件过滤键并对其进行排序:

blue_fruit = sorted([k for k in data.keys() if k[1] == 'blue'])
for k in blue_fruit:
  print k[0], data[k] # prints 'banana 24', etc

排序之所以有效,是因为如果元组的组成部分具有自然顺序,则它们具有自然顺序。

使用键作为完全成熟的对象,只需按即可过滤k.color == 'blue'

您不能真正将dicts用作键,但是可以创建一个最简单的类,例如class Foo(object): pass,并向其动态添加任何属性:

k = Foo()
k.color = 'blue'

这些实例可以用作字典键,但要注意其可变性!

With keys as tuples, you just filter the keys with given second component and sort it:

blue_fruit = sorted([k for k in data.keys() if k[1] == 'blue'])
for k in blue_fruit:
  print k[0], data[k] # prints 'banana 24', etc

Sorting works because tuples have natural ordering if their components have natural ordering.

With keys as rather full-fledged objects, you just filter by k.color == 'blue'.

You can’t really use dicts as keys, but you can create a simplest class like class Foo(object): pass and add any attributes to it on the fly:

k = Foo()
k.color = 'blue'

These instances can serve as dict keys, but beware their mutability!


回答 5

您可能有一个词典,其中的条目是其他词典的列表:

fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict

输出:

{‘香蕉’:[{‘黄色’:24}],’苹果’:[{‘红色’:12},{‘绿色’:14}]}

编辑:正如eumiro指出的那样,您可以使用词典字典:

fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict

输出:

{‘香蕉’:{‘黄色’:24},’苹果’:{‘绿色’:14,’红色’:12}}

You could have a dictionary where the entries are a list of other dictionaries:

fruit_dict = dict()
fruit_dict['banana'] = [{'yellow': 24}]
fruit_dict['apple'] = [{'red': 12}, {'green': 14}]
print fruit_dict

Output:

{‘banana’: [{‘yellow’: 24}], ‘apple’: [{‘red’: 12}, {‘green’: 14}]}

Edit: As eumiro pointed out, you could use a dictionary of dictionaries:

fruit_dict = dict()
fruit_dict['banana'] = {'yellow': 24}
fruit_dict['apple'] = {'red': 12, 'green': 14}
print fruit_dict

Output:

{‘banana’: {‘yellow’: 24}, ‘apple’: {‘green’: 14, ‘red’: 12}}


回答 6

从类似Trie的数据结构中有效提取此类数据。它还允许快速排序。内存效率可能不会那么好。

传统的trie将单词的每个字母存储为树中的节点。但是在您的情况下,您的“字母”是不同的。您正在存储字符串而不是字符。

它可能看起来像这样:

root:                Root
                     /|\
                    / | \
                   /  |  \     
fruit:       Banana Apple Strawberry
              / |      |     \
             /  |      |      \
color:     Blue Yellow Green  Blue
            /   |       |       \
           /    |       |        \
end:      24   100      12        0

看到这个链接:在Python中的特里

This type of data is efficiently pulled from a Trie-like data structure. It also allows for fast sorting. The memory efficiency might not be that great though.

A traditional trie stores each letter of a word as a node in the tree. But in your case your “alphabet” is different. You are storing strings instead of characters.

it might look something like this:

root:                Root
                     /|\
                    / | \
                   /  |  \     
fruit:       Banana Apple Strawberry
              / |      |     \
             /  |      |      \
color:     Blue Yellow Green  Blue
            /   |       |       \
           /    |       |        \
end:      24   100      12        0

see this link: trie in python


回答 7

您要独立使用两个键,因此有两个选择:

  1. 有两个类型的字典作为存储冗余数据{'banana' : {'blue' : 4, ...}, .... }{'blue': {'banana':4, ...} ...}。然后,搜索和排序很容易,但是您必须确保同时修改字典。

  2. 将其仅存储一个字典,然后编写对其进行迭代的函数,例如:

    d = {'banana' : {'blue' : 4, 'yellow':6}, 'apple':{'red':1} }
    
    blueFruit = [(fruit,d[fruit]['blue']) if d[fruit].has_key('blue') for fruit in d.keys()]

You want to use two keys independently, so you have two choices:

  1. Store the data redundantly with two dicts as {'banana' : {'blue' : 4, ...}, .... } and {'blue': {'banana':4, ...} ...}. Then, searching and sorting is easy but you have to make sure you modify the dicts together.

  2. Store it just one dict, and then write functions that iterate over them eg.:

    d = {'banana' : {'blue' : 4, 'yellow':6}, 'apple':{'red':1} }
    
    blueFruit = [(fruit,d[fruit]['blue']) if d[fruit].has_key('blue') for fruit in d.keys()]
    

为什么我不能在Python中使用列表作为字典键?

问题:为什么我不能在Python中使用列表作为字典键?

对于什么可以/不能用作python dict的键,我有些困惑。

dicked = {}
dicked[None] = 'foo'     # None ok
dicked[(1,3)] = 'baz'    # tuple ok
import sys
dicked[sys] = 'bar'      # wow, even a module is ok !
dicked[(1,[3])] = 'qux'  # oops, not allowed

因此,元组是一个不可变的类型,但是如果我在其中隐藏一个列表,那么它就不能成为键。.我不能像在模块内部一样轻松地隐藏一个列表吗?

我有一个模糊的想法,认为密钥必须是“可哈希的”,但是我只是承认自己对技术细节的无知。我不知道这里到底发生了什么。如果您尝试将列表用作键,而将哈希作为其存储位置,那会出什么问题呢?

I’m a bit confused about what can/can’t be used as a key for a python dict.

dicked = {}
dicked[None] = 'foo'     # None ok
dicked[(1,3)] = 'baz'    # tuple ok
import sys
dicked[sys] = 'bar'      # wow, even a module is ok !
dicked[(1,[3])] = 'qux'  # oops, not allowed

So a tuple is an immutable type but if I hide a list inside of it, then it can’t be a key.. couldn’t I just as easily hide a list inside a module?

I had some vague idea that that the key has to be “hashable” but I’m just going to admit my own ignorance about the technical details; I don’t know what’s really going on here. What would go wrong if you tried to use lists as keys, with the hash as, say, their memory location?


回答 0

Python Wiki中有一篇关于该主题的好文章:为什么列表不能成为字典键。如此处所述:

如果您尝试将列表用作键,而将哈希作为其存储位置,那会出什么问题呢?

可以在不真正破坏任何要求的情况下完成此操作,但是会导致意外的行为。通常将列表视为其值是从其内容的值派生的,例如在检查(不等式)时。可以理解的是,许多人希望您可以使用任何列表[1, 2]来获取相同的键,而您必须在其中保留完全相同的列表对象。但是,一旦修改了用作键的列表,按值查找就会中断,并且要通过标识查找,您需要保持完全相同的列表-这不需要任何其他常见的列表操作(至少我不能想到) )。

object无论如何,其他对象(例如模块)都会通过它们的对象标识产生更大的影响(这是您最后一次有两个不同的名为sys?的模块对象),并且无论如何都要进行比较。因此,当它们用作dict键时,在这种情况下也按标识进行比较就不足为奇了-甚至没有想到。

There’s a good article on the topic in the Python wiki: Why Lists Can’t Be Dictionary Keys. As explained there:

What would go wrong if you tried to use lists as keys, with the hash as, say, their memory location?

It can be done without really breaking any of the requirements, but it leads to unexpected behavior. Lists are generally treated as if their value was derived from their content’s values, for instance when checking (in-)equality. Many would – understandably – expect that you can use any list [1, 2] to get the same key, where you’d have to keep around exactly the same list object. But lookup by value breaks as soon as a list used as key is modified, and for lookup by identity requires you to keep around exactly the same list – which isn’t requires for any other common list operation (at least none I can think of).

Other objects such as modules and object make a much bigger deal out of their object identity anyway (when was the last time you had two distinct module objects called sys?), and are compared by that anyway. Therefore, it’s less surprising – or even expected – that they, when used as dict keys, compare by identity in that case as well.


回答 1

为什么我不能在Python中使用列表作为字典键?

>>> d = {repr([1,2,3]): 'value'}
{'[1, 2, 3]': 'value'}

(对于任何偶然发现此问题以寻求解决方案的人)

正如这里其他人所解释的,实际上您不能。但是,如果您确实要使用列表,则可以使用其字符串表示形式。

Why can’t I use a list as a dict key in python?

>>> d = {repr([1,2,3]): 'value'}
{'[1, 2, 3]': 'value'}

(for anybody who stumbles on this question looking for a way around it)

as explained by others here, indeed you cannot. You can however use its string representation instead if you really want to use your list.


回答 2

刚发现您可以将List更改为元组,然后将其用作键。

d = {tuple([1,2,3]): 'value'}

Just found you can change List into tuple, then use it as keys.

d = {tuple([1,2,3]): 'value'}

回答 3

问题在于元组是不可变的,而列表不是。考虑以下

d = {}
li = [1,2,3]
d[li] = 5
li.append(4)

应该d[li]返回什么?是相同的清单吗?怎么d[[1,2,3]]样 它具有相同的值,但列表不同吗?

最终,没有令人满意的答案。例如,如果唯一起作用的键是原始键,那么如果您没有对该键的引用,则无法再访问该值。使用其他所有允许的密钥,您可以构造一个密钥,而无需参考原始密钥。

如果我的两个建议都起作用,那么您将拥有非常不同的键,它们返回相同的值,这有点令人惊讶。如果仅原始内容有效,则您的密钥将很快失效,因为已修改了列表。

The issue is that tuples are immutable, and lists are not. Consider the following

d = {}
li = [1,2,3]
d[li] = 5
li.append(4)

What should d[li] return? Is it the same list? How about d[[1,2,3]]? It has the same values, but is a different list?

Ultimately, there is no satisfactory answer. For example, if the only key that works is the original key, then if you have no reference to that key, you can never again access the value. With every other allowed key, you can construct a key without a reference to the original.

If both of my suggestions work, then you have very different keys that return the same value, which is more than a little surprising. If only the original contents work, then your key will quickly go bad, since lists are made to be modified.


回答 4

这是一个答案http://wiki.python.org/moin/DictionaryKeys

如果您尝试将列表用作键,而将哈希作为其存储位置,那会出什么问题呢?

查找具有相同内容的不同列表将产生不同的结果,即使比较具有相同内容的列表也将它们视为等效。

在字典查找中使用列表文字怎么办?

Here’s an answer http://wiki.python.org/moin/DictionaryKeys

What would go wrong if you tried to use lists as keys, with the hash as, say, their memory location?

Looking up different lists with the same contents would produce different results, even though comparing lists with the same contents would indicate them as equivalent.

What about Using a list literal in a dictionary lookup?


回答 5

您的遮阳篷可以在这里找到:

为什么列表不能成为字典键

Python的新手常常想知道为什么,尽管语言既包含元组又包含列表类型,但是元组可用作字典键,而列表却不可用。这是一个经过深思熟虑的设计决定,可以通过首先了解Python词典的工作方式来最好地解释。

来源和更多信息:http : //wiki.python.org/moin/DictionaryKeys

Your awnser can be found here:

Why Lists Can’t Be Dictionary Keys

Newcomers to Python often wonder why, while the language includes both a tuple and a list type, tuples are usable as a dictionary keys, while lists are not. This was a deliberate design decision, and can best be explained by first understanding how Python dictionaries work.

Source & more info: http://wiki.python.org/moin/DictionaryKeys


回答 6

因为列表是可变的,所以dict键(和set成员)必须是可哈希的,并且对可变对象进行哈希处理是一个坏主意,因为哈希值基于实例属性进行计算。

在这个答案中,我将给出一些具体的例子,希望在现有答案的基础上增加价值。每个洞察力也适用于数据set结构的元素。

示例1:哈希可变对象,其中哈希值基于对象的可变特性。

>>> class stupidlist(list):
...     def __hash__(self):
...         return len(self)
... 
>>> stupid = stupidlist([1, 2, 3])
>>> d = {stupid: 0}
>>> stupid.append(4)
>>> stupid
[1, 2, 3, 4]
>>> d
{[1, 2, 3, 4]: 0}
>>> stupid in d
False
>>> stupid in d.keys()
False
>>> stupid in list(d.keys())
True

突变后stupid,不能在字典不再因为散列变化发现。仅对字典的键列表进行线性扫描才能找到stupid

例2:…但是为什么不只是一个恒定的哈希值?

>>> class stupidlist2(list):
...     def __hash__(self):
...         return id(self)
... 
>>> stupidA = stupidlist2([1, 2, 3])
>>> stupidB = stupidlist2([1, 2, 3])
>>> 
>>> stupidA == stupidB
True
>>> stupidA in {stupidB: 0}
False

这也不是一个好主意,因为相等的对象应该相同地散列,以便您可以在 dict或中set

例子3:…好吧,在所有实例中保持不变的哈希值呢?

>>> class stupidlist3(list):
...     def __hash__(self):
...         return 1
... 
>>> stupidC = stupidlist3([1, 2, 3])
>>> stupidD = stupidlist3([1, 2, 3])
>>> stupidE = stupidlist3([1, 2, 3, 4])
>>> 
>>> stupidC in {stupidD: 0}
True
>>> stupidC in {stupidE: 0}
False
>>> d = {stupidC: 0}
>>> stupidC.append(5)
>>> stupidC in d
True

事情似乎按预期工作,但是请考虑发生了什么:当类的所有实例产生相同的哈希值时,只要一个实例中有两个以上的实例作为键,您就会发生哈希冲突。 dict或存在set

使用my_dict[key]key in my_dict(或item in my_set)需要执行stupidlist3与字典键中实例相同的次数相等的检查(在最坏的情况下)。在这一点上,字典的目的-O(1)查找-被完全击败了。以下时间(使用IPython完成)对此进行了演示。

示例3的一些时间

>>> lists_list = [[i]  for i in range(1000)]
>>> stupidlists_set = {stupidlist3([i]) for i in range(1000)}
>>> tuples_set = {(i,) for i in range(1000)}
>>> l = [999]
>>> s = stupidlist3([999])
>>> t = (999,)
>>> 
>>> %timeit l in lists_list
25.5 µs ± 442 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit s in stupidlists_set
38.5 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit t in tuples_set
77.6 ns ± 1.5 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

如您所见,我们的成员资格测试stupidlists_set比整个范围的线性扫描要慢lists_list,而您在一组没有哈希冲突的情况下拥有预期的超快查找时间(因子500)。


TL; DR:您可以将其tuple(yourlist)用作dict键,因为元组是不可变且可哈希的。

Because lists are mutable, dict keys (and set members) need to be hashable, and hashing mutable objects is a bad idea because hash values should be computed on the basis of instance attributes.

In this answer, I will give some concrete examples, hopefully adding value on top of the existing answers. Every insight applies to the elements of the set datastructure as well.

Example 1: hashing a mutable object where the hash value is based on a mutable characteristic of the object.

>>> class stupidlist(list):
...     def __hash__(self):
...         return len(self)
... 
>>> stupid = stupidlist([1, 2, 3])
>>> d = {stupid: 0}
>>> stupid.append(4)
>>> stupid
[1, 2, 3, 4]
>>> d
{[1, 2, 3, 4]: 0}
>>> stupid in d
False
>>> stupid in d.keys()
False
>>> stupid in list(d.keys())
True

After mutating stupid, it cannot be found in the dict any longer because the hash changed. Only a linear scan over the list of the dict’s keys finds stupid.

Example 2: … but why not just a constant hash value?

>>> class stupidlist2(list):
...     def __hash__(self):
...         return id(self)
... 
>>> stupidA = stupidlist2([1, 2, 3])
>>> stupidB = stupidlist2([1, 2, 3])
>>> 
>>> stupidA == stupidB
True
>>> stupidA in {stupidB: 0}
False

That’s not a good idea as well because equal objects should hash identically such that you can find them in a dict or set.

Example 3: … ok, what about constant hashes across all instances?!

>>> class stupidlist3(list):
...     def __hash__(self):
...         return 1
... 
>>> stupidC = stupidlist3([1, 2, 3])
>>> stupidD = stupidlist3([1, 2, 3])
>>> stupidE = stupidlist3([1, 2, 3, 4])
>>> 
>>> stupidC in {stupidD: 0}
True
>>> stupidC in {stupidE: 0}
False
>>> d = {stupidC: 0}
>>> stupidC.append(5)
>>> stupidC in d
True

Things seem to work as expected, but think about what’s happening: when all instances of your class produce the same hash value, you will have a hash collision whenever there are more than two instances as keys in a dict or present in a set.

Finding the right instance with my_dict[key] or key in my_dict (or item in my_set) needs to perform as many equality checks as there are instances of stupidlist3 in the dict’s keys (in the worst case). At this point, the purpose of the dictionary – O(1) lookup – is completely defeated. This is demonstrated in the following timings (done with IPython).

Some Timings for Example 3

>>> lists_list = [[i]  for i in range(1000)]
>>> stupidlists_set = {stupidlist3([i]) for i in range(1000)}
>>> tuples_set = {(i,) for i in range(1000)}
>>> l = [999]
>>> s = stupidlist3([999])
>>> t = (999,)
>>> 
>>> %timeit l in lists_list
25.5 µs ± 442 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit s in stupidlists_set
38.5 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit t in tuples_set
77.6 ns ± 1.5 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

As you can see, the membership test in our stupidlists_set is even slower than a linear scan over the whole lists_list, while you have the expected super fast lookup time (factor 500) in a set without loads of hash collisions.


TL; DR: you can use tuple(yourlist) as dict keys, because tuples are immutable and hashable.


回答 7

您问题的简单答案是,类列表未实现方法散列,该散列对于任何希望用作字典中键的对象都是必需的。但是散列的原因不相同方式实现它在说,元组类(基于容器的内容)是因为列表是可变的,以便编辑列表将需要散列重新计算,这可能意味着在列表中现在位于基础哈希表中的错误存储桶中。请注意,由于您无法修改元组(不可变的),因此不会遇到此问题。

附带说明,dictobjects查找的实际实现基于Knuth Vol。的算法D。3秒 6.4。如果您有这本书,那么可能值得一读,此外,如果您真的非常有兴趣,则可以在这里查看开发人员对dictobject实际实现的评论。它详细介绍了它的工作原理。您可能也对感兴趣的字典的实现有一个python讲座。它们遍历了键的定义以及前几分钟的哈希值。

The simple answer to your question is that the class list does not implement the method hash which is required for any object which wishes to be used as a key in a dictionary. However the reason why hash is not implemented the same way it is in say the tuple class (based on the content of the container) is because a list is mutable so editing the list would require the hash to be recalculated which may mean the list in now located in the wrong bucket within the underling hash table. Note that since you cannot modify a tuple (immutable) it doesn’t run into this problem.

As a side note, the actual implementation of the dictobjects lookup is based on Algorithm D from Knuth Vol. 3, Sec. 6.4. If you have that book available to you it might be a worthwhile read, in addition if you’re really, really interested you may like to take a peek at the developer comments on the actual implementation of dictobject here. It goes into great detail as to exactly how it works. There is also a python lecture on the implementation of dictionaries which you may be interested in. They go through the definition of a key and what a hash is in the first few minutes.


回答 8

根据Python 2.7.2文档:

如果对象的哈希值在其生命周期内不发生变化(需要使用hash()方法),并且可以与其他对象进行比较(需要使用eq()或cmp()方法),则该对象是可哈希的。比较相等的可哈希对象必须具有相同的哈希值。

散列性使对象可用作字典键和set成员,因为这些数据结构在内部使用散列值。

Python的所有不可变内置对象都是可哈希的,而没有可变容器(例如列表或字典)是可哈希的。作为用户定义类实例的对象默认情况下是可哈希的;它们都比较不相等,并且其哈希值是其id()。

从不能添加,删除或替换其元素的意义上说,元组是不可变的,但是元素本身可能是可变的。列表的哈希值取决于其元素的哈希值,因此当您更改元素时它也会改变。

对列表散列使用id意味着所有列表的比较方式不同,这将令人惊讶且不便。

According to the Python 2.7.2 documentation:

An object is hashable if it has a hash value which never changes during its lifetime (it needs a hash() method), and can be compared to other objects (it needs an eq() or cmp() method). Hashable objects which compare equal must have the same hash value.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal, and their hash value is their id().

A tuple is immutable in the sense that you cannot add, remove or replace its elements, but the elements themselves may be mutable. List’s hash value depends on the hash values of its elements, and so it changes when you change the elements.

Using id’s for list hashes would imply that all lists compare differently, which would be surprising and inconvenient.


回答 9

字典是一个HashMap,它存储您的键的映射,将值转换为哈希的新键以及值映射。

类似于(伪代码):

{key : val}  
hash(key) = val

如果您想知道哪些可用选项可以用作字典的键。然后

任何可散列的内容(可以转换为散列,并保持静态值,即不可变,以形成如上所述的散列键)均符合条件,但是列表或集合对象可以随时随地变化,因此hash(key)也应只是为了与您的列表或集合同步而变化。

你可以试试 :

hash(<your key here>)

如果工作正常,则可以将其用作字典的键,也可以将其转换为可哈希的值。


简而言之 :

  1. 将该列表转换为tuple(<your list>)
  2. 将该列表转换为str(<your list>)

A Dictionary is a HashMap it stores map of your keys, value converted to a hashed new key and value mapping.

something like (psuedo code):

{key : val}  
hash(key) = val

If you are wondering which are available options that can be used as key for your dictionary. Then

anything which is hashable(can be converted to hash, and hold static value i.e immutable so as to make a hashed key as stated above) is eligible but as list or set objects can be vary on the go so hash(key) should also needs to vary just to be in sync with your list or set.

You can try :

hash(<your key here>)

If it works fine it can be used as key for your dictionary or else convert it to something hashable.


Inshort :

  1. Convert that list to tuple(<your list>).
  2. Convert that list to str(<your list>).

回答 10

dict键必须是可哈希的。列表是可变的,它们不提供有效的哈希方法。

dict keys need to be hashable. Lists are Mutable and they do not provide a valid hash method.


像sum这样的Python元素元组操作

问题:像sum这样的Python元素元组操作

无论如何,有没有让Python中的元组操作像这样工作:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)

代替:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)

我知道它是这样工作的,因为__add____mul__方法被定义为那样工作。因此,唯一的方法是重新定义它们?

Is there anyway to get tuple operations in Python to work like this:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(4,4,4)

instead of:

>>> a = (1,2,3)
>>> b = (3,2,1)
>>> a + b
(1,2,3,3,2,1)

I know it works like that because the __add__ and __mul__ methods are defined to work like that. So the only way would be to redefine them?


回答 0

import operator
tuple(map(operator.add, a, b))
import operator
tuple(map(operator.add, a, b))

回答 1

使用所有内置插件

tuple(map(sum, zip(a, b)))

Using all built-ins..

tuple(map(sum, zip(a, b)))

回答 2

此解决方案不需要导入:

tuple(map(lambda x, y: x + y, tuple1, tuple2))

This solution doesn’t require an import:

tuple(map(lambda x, y: x + y, tuple1, tuple2))

回答 3

对前两个答案进行了某种组合,并对Ironfroggy的代码进行了调整,以使其返回一个元组:

import operator

class stuple(tuple):
    def __add__(self, other):
        return self.__class__(map(operator.add, self, other))
        # obviously leaving out checking lengths

>>> a = stuple([1,2,3])
>>> b = stuple([3,2,1])
>>> a + b
(4, 4, 4)

注意:使用self.__class__代替stuple简化子类化。

Sort of combined the first two answers, with a tweak to ironfroggy’s code so that it returns a tuple:

import operator

class stuple(tuple):
    def __add__(self, other):
        return self.__class__(map(operator.add, self, other))
        # obviously leaving out checking lengths

>>> a = stuple([1,2,3])
>>> b = stuple([3,2,1])
>>> a + b
(4, 4, 4)

Note: using self.__class__ instead of stuple to ease subclassing.


回答 4

from numpy import *

a = array( [1,2,3] )
b = array( [3,2,1] )

print a + b

array([4,4,4])

参见http://www.scipy.org/Tentative_NumPy_Tutorial

from numpy import array

a = array( [1,2,3] )
b = array( [3,2,1] )

print a + b

gives array([4,4,4]).

See http://www.scipy.org/Tentative_NumPy_Tutorial


回答 5

可以使用生成器理解来代替map。内置的地图功能并不是过时的,但是对于大多数人来说,其可读性不如列表/生成器/字典理解,因此,我建议一般不要使用地图功能。

tuple(p+q for p, q in zip(a, b))

Generator comprehension could be used instead of map. Built-in map function is not obsolete but it’s less readable for most people than list/generator/dict comprehension, so I’d recommend not to use map function in general.

tuple(p+q for p, q in zip(a, b))

回答 6

没有类定义的简单解决方案,返回元组

import operator
tuple(map(operator.add,a,b))

simple solution without class definition that returns tuple

import operator
tuple(map(operator.add,a,b))

回答 7

所有生成器解决方案。不确定性能(不过itertools很快)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))

All generator solution. Not sure on performance (itertools is fast, though)

import itertools
tuple(x+y for x, y in itertools.izip(a,b))

回答 8

是。但是您不能重新定义内置类型。您必须将它们子类化:

类MyTuple(tuple):
    def __add __(自己,其他):
         如果len(self)!= len(other):
             引发ValueError(“元组长度不匹配”)
         返回MyTuple(对于zip中的(x,y)为x(y,y)(self,other))

Yes. But you can’t redefine built-in types. You have to subclass them:

class MyTuple(tuple):
    def __add__(self, other):
         if len(self) != len(other):
             raise ValueError("tuple lengths don't match")
         return MyTuple(x + y for (x, y) in zip(self, other))

回答 9

甚至更简单,无需使用地图,您可以做到这一点

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)

even simpler and without using map, you can do that

>>> tuple(sum(i) for i in zip((1, 2, 3), (3, 2, 1)))
(4, 4, 4)

回答 10

我目前将“元组”类子类化以重载+,-和*。我发现它使代码更漂亮,并使编写代码更容易。

class tupleN(tuple):
    def __add__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x+y for x,y in zip(self,other))
    def __sub__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x-y for x,y in zip(self,other))
    def __mul__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x*y for x,y in zip(self,other))


t1 = tupleN((1,3,3))
t2 = tupleN((1,3,4))
print(t1 + t2, t1 - t2, t1 * t2, t1 + t1 - t1 - t1)
(2, 6, 7) (0, 0, -1) (1, 9, 12) (0, 0, 0)

I currently subclass the “tuple” class to overload +,- and *. I find it makes the code beautiful and writing the code easier.

class tupleN(tuple):
    def __add__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x+y for x,y in zip(self,other))
    def __sub__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x-y for x,y in zip(self,other))
    def __mul__(self, other):
        if len(self) != len(other):
             return NotImplemented
        else:
             return tupleN(x*y for x,y in zip(self,other))


t1 = tupleN((1,3,3))
t2 = tupleN((1,3,4))
print(t1 + t2, t1 - t2, t1 * t2, t1 + t1 - t1 - t1)
(2, 6, 7) (0, 0, -1) (1, 9, 12) (0, 0, 0)

回答 11

如果有人需要平均一个元组列表:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))

In case someone need to average a list of tuples:

import operator 
from functools import reduce
tuple(reduce(lambda x, y: tuple(map(operator.add, x, y)),list_of_tuples))

如何将逗号分隔的字符串转换为Python中的列表?

问题:如何将逗号分隔的字符串转换为Python中的列表?

给定一个字符串,该字符串是由逗号分隔的多个值的序列:

mStr = 'A,B,C,D,E' 

如何将字符串转换为列表?

mList = ['A', 'B', 'C', 'D', 'E']

Given a string that is a sequence of several values separated by a commma:

mStr = 'A,B,C,D,E' 

How do I convert the string to a list?

mList = ['A', 'B', 'C', 'D', 'E']

回答 0

您可以使用str.split方法。

>>> my_string = 'A,B,C,D,E'
>>> my_list = my_string.split(",")
>>> print my_list
['A', 'B', 'C', 'D', 'E']

如果要将其转换为元组,只需

>>> print tuple(my_list)
('A', 'B', 'C', 'D', 'E')

如果您希望追加到列表,请尝试以下操作:

>>> my_list.append('F')
>>> print my_list
['A', 'B', 'C', 'D', 'E', 'F']

You can use the str.split method.

>>> my_string = 'A,B,C,D,E'
>>> my_list = my_string.split(",")
>>> print my_list
['A', 'B', 'C', 'D', 'E']

If you want to convert it to a tuple, just

>>> print tuple(my_list)
('A', 'B', 'C', 'D', 'E')

If you are looking to append to a list, try this:

>>> my_list.append('F')
>>> print my_list
['A', 'B', 'C', 'D', 'E', 'F']

回答 1

对于字符串中包含的整数,如果要避免将它们int分别转换为整数,可以执行以下操作:

mList = [int(e) if e.isdigit() else e for e in mStr.split(',')]

这称为列表理解,它基于集合构建器符号。

例如:

>>> mStr = "1,A,B,3,4"
>>> mList = [int(e) if e.isdigit() else e for e in mStr.split(',')]
>>> mList
>>> [1,'A','B',3,4]

In the case of integers that are included at the string, if you want to avoid casting them to int individually you can do:

mList = [int(e) if e.isdigit() else e for e in mStr.split(',')]

It is called list comprehension, and it is based on set builder notation.

ex:

>>> mStr = "1,A,B,3,4"
>>> mList = [int(e) if e.isdigit() else e for e in mStr.split(',')]
>>> mList
>>> [1,'A','B',3,4]

回答 2

>>> some_string='A,B,C,D,E'
>>> new_tuple= tuple(some_string.split(','))
>>> new_tuple
('A', 'B', 'C', 'D', 'E')
>>> some_string='A,B,C,D,E'
>>> new_tuple= tuple(some_string.split(','))
>>> new_tuple
('A', 'B', 'C', 'D', 'E')

回答 3

您可以使用此功能将以逗号分隔的单个字符串转换为list-

def stringtolist(x):
    mylist=[]
    for i in range(0,len(x),2):
        mylist.append(x[i])
    return mylist

You can use this function to convert comma-delimited single character strings to list-

def stringtolist(x):
    mylist=[]
    for i in range(0,len(x),2):
        mylist.append(x[i])
    return mylist

回答 4

#splits string according to delimeters 
'''
Let's make a function that can split a string
into list according the given delimeters. 
example data: cat;dog:greff,snake/
example delimeters: ,;- /|:
'''
def string_to_splitted_array(data,delimeters):
    #result list
    res = []
    # we will add chars into sub_str until
    # reach a delimeter
    sub_str = ''
    for c in data: #iterate over data char by char
        # if we reached a delimeter, we store the result 
        if c in delimeters: 
            # avoid empty strings
            if len(sub_str)>0:
                # looks like a valid string.
                res.append(sub_str)
                # reset sub_str to start over
                sub_str = ''
        else:
            # c is not a deilmeter. then it is 
            # part of the string.
            sub_str += c
    # there may not be delimeter at end of data. 
    # if sub_str is not empty, we should att it to list. 
    if len(sub_str)>0:
        res.append(sub_str)
    # result is in res 
    return res

# test the function. 
delimeters = ',;- /|:'
# read the csv data from console. 
csv_string = input('csv string:')
#lets check if working. 
splitted_array = string_to_splitted_array(csv_string,delimeters)
print(splitted_array)
#splits string according to delimeters 
'''
Let's make a function that can split a string
into list according the given delimeters. 
example data: cat;dog:greff,snake/
example delimeters: ,;- /|:
'''
def string_to_splitted_array(data,delimeters):
    #result list
    res = []
    # we will add chars into sub_str until
    # reach a delimeter
    sub_str = ''
    for c in data: #iterate over data char by char
        # if we reached a delimeter, we store the result 
        if c in delimeters: 
            # avoid empty strings
            if len(sub_str)>0:
                # looks like a valid string.
                res.append(sub_str)
                # reset sub_str to start over
                sub_str = ''
        else:
            # c is not a deilmeter. then it is 
            # part of the string.
            sub_str += c
    # there may not be delimeter at end of data. 
    # if sub_str is not empty, we should att it to list. 
    if len(sub_str)>0:
        res.append(sub_str)
    # result is in res 
    return res

# test the function. 
delimeters = ',;- /|:'
# read the csv data from console. 
csv_string = input('csv string:')
#lets check if working. 
splitted_array = string_to_splitted_array(csv_string,delimeters)
print(splitted_array)

回答 5

考虑以下内容以处理空字符串的情况:

>>> my_string = 'A,B,C,D,E'
>>> my_string.split(",") if my_string else []
['A', 'B', 'C', 'D', 'E']
>>> my_string = ""
>>> my_string.split(",") if my_string else []
[]

Consider the following in order to handle the case of an empty string:

>>> my_string = 'A,B,C,D,E'
>>> my_string.split(",") if my_string else []
['A', 'B', 'C', 'D', 'E']
>>> my_string = ""
>>> my_string.split(",") if my_string else []
[]

回答 6

您可以拆分该字符串,并直接获取列表:

mStr = 'A,B,C,D,E'
list1 = mStr.split(',')
print(list1)

输出:

['A', 'B', 'C', 'D', 'E']

您还可以将其转换为n元组:

print(tuple(list1))

输出:

('A', 'B', 'C', 'D', 'E')

You can split that string on , and directly get a list:

mStr = 'A,B,C,D,E'
list1 = mStr.split(',')
print(list1)

Output:

['A', 'B', 'C', 'D', 'E']

You can also convert it to an n-tuple:

print(tuple(list1))

Output:

('A', 'B', 'C', 'D', 'E')


Python将项目添加到元组

问题:Python将项目添加到元组

我有一些object.ID-s,我尝试将其作为元组存储在用户会话中。当我添加第一个时,它可以工作,但是元组看起来像,(u'2',)但是当我尝试使用mytuple = mytuple + new.idgot error 添加新的时can only concatenate tuple (not "unicode") to tuple

I have some object.ID-s which I try to store in the user session as tuple. When I add first one it works but tuple looks like (u'2',) but when I try to add new one using mytuple = mytuple + new.id got error can only concatenate tuple (not "unicode") to tuple.


回答 0

您需要将第二个元素设为1元组,例如:

a = ('2',)
b = 'z'
new = a + (b,)

You need to make the second element a 1-tuple, eg:

a = ('2',)
b = 'z'
new = a + (b,)

回答 1

从Python 3.5(PEP 448)开始,您可以在元组,列表集和字典中进行解包:

a = ('2',)
b = 'z'
new = (*a, b)

Since Python 3.5 (PEP 448) you can do unpacking within a tuple, list set, and dict:

a = ('2',)
b = 'z'
new = (*a, b)

回答 2

从元组到列表再到元组:

a = ('2',)
b = 'b'

l = list(a)
l.append(b)

tuple(l)

或附有较长的项目清单

a = ('2',)
items = ['o', 'k', 'd', 'o']

l = list(a)

for x in items:
    l.append(x)

print tuple(l)

给你

>>> 
('2', 'o', 'k', 'd', 'o')

这里的重点是:列表是可变的序列类型。因此,您可以通过添加或删除元素来更改给定列表。元组是不可变的序列类型。您不能更改元组。因此,您必须创建一个新的

From tuple to list to tuple :

a = ('2',)
b = 'b'

l = list(a)
l.append(b)

tuple(l)

Or with a longer list of items to append

a = ('2',)
items = ['o', 'k', 'd', 'o']

l = list(a)

for x in items:
    l.append(x)

print tuple(l)

gives you

>>> 
('2', 'o', 'k', 'd', 'o')

The point here is: List is a mutable sequence type. So you can change a given list by adding or removing elements. Tuple is an immutable sequence type. You can’t change a tuple. So you have to create a new one.


回答 3

元组只能允许添加tuple到其中。最好的方法是:

mytuple =(u'2',)
mytuple +=(new.id,)

我使用以下数据尝试了相同的情况,但似乎一切正常。

>>> mytuple = (u'2',)
>>> mytuple += ('example text',)
>>> print mytuple
(u'2','example text')

Tuple can only allow adding tuple to it. The best way to do it is:

mytuple =(u'2',)
mytuple +=(new.id,)

I tried the same scenario with the below data it all seems to be working fine.

>>> mytuple = (u'2',)
>>> mytuple += ('example text',)
>>> print mytuple
(u'2','example text')

回答 4

>>> x = (u'2',)
>>> x += u"random string"

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    x += u"random string"
TypeError: can only concatenate tuple (not "unicode") to tuple
>>> x += (u"random string", )  # concatenate a one-tuple instead
>>> x
(u'2', u'random string')
>>> x = (u'2',)
>>> x += u"random string"

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    x += u"random string"
TypeError: can only concatenate tuple (not "unicode") to tuple
>>> x += (u"random string", )  # concatenate a one-tuple instead
>>> x
(u'2', u'random string')

回答 5

#1表格

a = ('x', 'y')
b = a + ('z',)
print(b)

#2表格

a = ('x', 'y')
b = a + tuple('b')
print(b)

#1 form

a = ('x', 'y')
b = a + ('z',)
print(b)

#2 form

a = ('x', 'y')
b = a + tuple('b')
print(b)

回答 6

最简单的说,添加到元组的最简单方法是用括号和逗号将要添加的元素括起来。

t = ('a', 4, 'string')
t = t + (5.0,)
print(t)

out: ('a', 4, 'string', 5.0)

Bottom line, the easiest way to append to a tuple is to enclose the element being added with parentheses and a comma.

t = ('a', 4, 'string')
t = t + (5.0,)
print(t)

out: ('a', 4, 'string', 5.0)

从元组中获得一个价值

问题:从元组中获得一个价值

有没有一种方法可以使用表达式从Python元组中获取一个值?

def tup():
  return (3, "hello")

i = 5 + tup()  # I want to add just the three

我知道我可以这样做:

(j, _) = tup()
i = 5 + j

但这会给我的函数增加几十行,使其长度加倍。

Is there a way to get one value from a tuple in Python using expressions?

def tup():
  return (3, "hello")

i = 5 + tup()  # I want to add just the three

I know I can do this:

(j, _) = tup()
i = 5 + j

But that would add a few dozen lines to my function, doubling its length.


回答 0

你可以写

i = 5 + tup()[0]

元组可以像列表一样被索引。

元组和列表之间的主要区别是元组是不可变的-您不能将元组的元素设置为不同的值,也不能像从列表中那样添加或删除元素。但是除此之外,在大多数情况下,它们的工作原理几乎相同。

You can write

i = 5 + tup()[0]

Tuples can be indexed just like lists.

The main difference between tuples and lists is that tuples are immutable – you can’t set the elements of a tuple to different values, or add or remove elements like you can from a list. But other than that, in most situations, they work pretty much the same.


回答 1

对于以后寻求答案的任何人,我想对这个问题给出更清晰的答案。

# for making a tuple
my_tuple = (89, 32)
my_tuple_with_more_values = (1, 2, 3, 4, 5, 6)

# to concatenate tuples
another_tuple = my_tuple + my_tuple_with_more_values
print(another_tuple)
# (89, 32, 1, 2, 3, 4, 5, 6)

# getting a value from a tuple is similar to a list
first_val = my_tuple[0]
second_val = my_tuple[1]

# if you have a function called my_tuple_fun that returns a tuple,
# you might want to do this
my_tuple_fun()[0]
my_tuple_fun()[1]

# or this
v1, v2 = my_tuple_fun()

希望这能为需要它的人进一步解决。

For anyone in the future looking for an answer, I would like to give a much clearer answer to the question.

# for making a tuple
my_tuple = (89, 32)
my_tuple_with_more_values = (1, 2, 3, 4, 5, 6)

# to concatenate tuples
another_tuple = my_tuple + my_tuple_with_more_values
print(another_tuple)
# (89, 32, 1, 2, 3, 4, 5, 6)

# getting a value from a tuple is similar to a list
first_val = my_tuple[0]
second_val = my_tuple[1]

# if you have a function called my_tuple_fun that returns a tuple,
# you might want to do this
my_tuple_fun()[0]
my_tuple_fun()[1]

# or this
v1, v2 = my_tuple_fun()

Hope this clears things up further for those that need it.


python元组到字典

问题:python元组到字典

对于元组,t = ((1, 'a'),(2, 'b')) dict(t)返回{1: 'a', 2: 'b'}

有没有一种好的方法{'a': 1, 'b': 2}(交换键和值)?

最终,我希望能够返回1给定'a'2给定'b',也许转换为字典不是最好的方法。

For the tuple, t = ((1, 'a'),(2, 'b')) dict(t) returns {1: 'a', 2: 'b'}

Is there a good way to get {'a': 1, 'b': 2} (keys and vals swapped)?

Ultimately, I want to be able to return 1 given 'a' or 2 given 'b', perhaps converting to a dict is not the best way.


回答 0

尝试:

>>> t = ((1, 'a'),(2, 'b'))
>>> dict((y, x) for x, y in t)
{'a': 1, 'b': 2}

Try:

>>> t = ((1, 'a'),(2, 'b'))
>>> dict((y, x) for x, y in t)
{'a': 1, 'b': 2}

回答 1

稍微简单一些的方法:

>>> t = ((1, 'a'),(2, 'b'))
>>> dict(map(reversed, t))
{'a': 1, 'b': 2}

A slightly simpler method:

>>> t = ((1, 'a'),(2, 'b'))
>>> dict(map(reversed, t))
{'a': 1, 'b': 2}

回答 2

如果您使用的是python 2.7,则更加简洁:

>>> t = ((1,'a'),(2,'b'))
>>> {y:x for x,y in t}
{'a':1, 'b':2}

Even more concise if you are on python 2.7:

>>> t = ((1,'a'),(2,'b'))
>>> {y:x for x,y in t}
{'a':1, 'b':2}

回答 3

>>> dict([('hi','goodbye')])
{'hi': 'goodbye'}

要么:

>>> [ dict([i]) for i in (('CSCO', 21.14), ('CSCO', 21.14), ('CSCO', 21.14), ('CSCO', 21.14)) ]
[{'CSCO': 21.14}, {'CSCO': 21.14}, {'CSCO': 21.14}, {'CSCO': 21.14}]
>>> dict([('hi','goodbye')])
{'hi': 'goodbye'}

Or:

>>> [ dict([i]) for i in (('CSCO', 21.14), ('CSCO', 21.14), ('CSCO', 21.14), ('CSCO', 21.14)) ]
[{'CSCO': 21.14}, {'CSCO': 21.14}, {'CSCO': 21.14}, {'CSCO': 21.14}]

回答 4

如果同一个键有多个值,则以下代码会将这些值附加到与它们的键相对应的列表中,

d = dict()
for x,y in t:
    if(d.has_key(y)):
        d[y].append(x)
    else:
        d[y] = [x]

If there are multiple values for the same key, the following code will append those values to a list corresponding to their key,

d = dict()
for x,y in t:
    if(d.has_key(y)):
        d[y].append(x)
    else:
        d[y] = [x]

回答 5

以下是几种方法:

>>> t = ((1, 'a'), (2, 'b'))

>>> # using reversed function
>>> dict(reversed(i) for i in t)
{'a': 1, 'b': 2}

>>> # using slice operator
>>> dict(i[::-1] for i in t)
{'a': 1, 'b': 2}

Here are couple ways of doing it:

>>> t = ((1, 'a'), (2, 'b'))

>>> # using reversed function
>>> dict(reversed(i) for i in t)
{'a': 1, 'b': 2}

>>> # using slice operator
>>> dict(i[::-1] for i in t)
{'a': 1, 'b': 2}

将namedtuple转换成字典

问题:将namedtuple转换成字典

我在python中有一个命名的tuple类

class Town(collections.namedtuple('Town', [
    'name', 
    'population',
    'coordinates',
    'population', 
    'capital', 
    'state_bird'])):
    # ...

我想将Town实例转换成字典。我不希望它与城镇中字段的名称或数量严格相关。

有没有一种方法可以编写它,以便我可以添加更多字段,或者传入完全不同的命名元组并获得字典。

我无法更改其他人代码中的原始类定义。因此,我需要以一个Town实例为例,并将其转换为字典。

I have a named tuple class in python

class Town(collections.namedtuple('Town', [
    'name', 
    'population',
    'coordinates',
    'population', 
    'capital', 
    'state_bird'])):
    # ...

I’d like to convert Town instances into dictionaries. I don’t want it to be rigidly tied to the names or number of the fields in a Town.

Is there a way to write it such that I could add more fields, or pass an entirely different named tuple in and get a dictionary.

I can not alter the original class definition as its in someone else’s code. So I need to take an instance of a Town and convert it to a dictionary.


回答 0

TL; DR:_asdict为此提供了一种方法。

这是用法的演示:

>>> fields = ['name', 'population', 'coordinates', 'capital', 'state_bird']
>>> Town = collections.namedtuple('Town', fields)
>>> funkytown = Town('funky', 300, 'somewhere', 'lipps', 'chicken')
>>> funkytown._asdict()
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

这是一个已记录的namedtuples 方法,即,与python中的常规约定不同,该方法名上的前划线并不妨碍使用。随着加入namedtuples其他方法,_make_replace_source_fields,它有下划线只尝试和防止可能的字段名的冲突。


注意: 对于一些2.7.5 <python版本<3.5.0的代码,您可能会看到以下版本:

>>> vars(funkytown)
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

有一段时间,文档提到_asdict过时了(请参阅此处),并建议使用内置方法vars。那个建议现在已经过时了。为了修复与子类相关的错误__dict__此commit再次删除了namedtuples上存在的属性。

TL;DR: there’s a method _asdict provided for this.

Here is a demonstration of the usage:

>>> fields = ['name', 'population', 'coordinates', 'capital', 'state_bird']
>>> Town = collections.namedtuple('Town', fields)
>>> funkytown = Town('funky', 300, 'somewhere', 'lipps', 'chicken')
>>> funkytown._asdict()
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

This is a documented method of namedtuples, i.e. unlike the usual convention in python the leading underscore on the method name isn’t there to discourage use. Along with the other methods added to namedtuples, _make, _replace, _source, _fields, it has the underscore only to try and prevent conflicts with possible field names.


Note: For some 2.7.5 < python version < 3.5.0 code out in the wild, you might see this version:

>>> vars(funkytown)
OrderedDict([('name', 'funky'),
             ('population', 300),
             ('coordinates', 'somewhere'),
             ('capital', 'lipps'),
             ('state_bird', 'chicken')])

For a while the documentation had mentioned that _asdict was obsolete (see here), and suggested to use the built-in method vars. That advice is now outdated; in order to fix a bug related to subclassing, the __dict__ property which was present on namedtuples has again been removed by this commit.


回答 1

namedtuple实例上有一个内置方法_asdict

正如评论中所讨论的,在某些版本上vars()也可以这样做,但是它显然高度依赖于构建细节,而_asdict应该是可靠的。在某些版本_asdict中,已将其标记为已弃用,但注释表明从3.4版开始,情况已不再如此。

There’s a built in method on namedtuple instances for this, _asdict.

As discussed in the comments, on some versions vars() will also do it, but it’s apparently highly dependent on build details, whereas _asdict should be reliable. In some versions _asdict was marked as deprecated, but comments indicate that this is no longer the case as of 3.4.


回答 2

在Ubuntu 14.04 LTS版本的python2.7和python3.4上,该__dict__属性按预期工作。该_asdict 方法也有效,但我倾向于使用标准定义的统一属性api而不是本地化的非统一api。

$ python2.7

# Works on:
# Python 2.7.6 (default, Jun 22 2015, 17:58:13)  [GCC 4.8.2] on linux2
# Python 3.4.3 (default, Oct 14 2015, 20:28:29)  [GCC 4.8.4] on linux

import collections

Color = collections.namedtuple('Color', ['r', 'g', 'b'])
red = Color(r=256, g=0, b=0)

# Access the namedtuple as a dict
print(red.__dict__['r'])  # 256

# Drop the namedtuple only keeping the dict
red = red.__dict__
print(red['r'])  #256

视为字典是获取表示词义的字典的语义方式(至少据我所知)。


汇总主要python版本和平台及其对它们的支持会很高兴__dict__,目前如上所述,我只有一个平台版本和两个python版本。

| Platform                      | PyVer     | __dict__ | _asdict |
| --------------------------    | --------- | -------- | ------- |
| Ubuntu 14.04 LTS              | Python2.7 | yes      | yes     |
| Ubuntu 14.04 LTS              | Python3.4 | yes      | yes     |
| CentOS Linux release 7.4.1708 | Python2.7 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.4 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.6 | no       | yes     |

On Ubuntu 14.04 LTS versions of python2.7 and python3.4 the __dict__ property worked as expected. The _asdict method also worked, but I’m inclined to use the standards-defined, uniform, property api instead of the localized non-uniform api.

$ python2.7

# Works on:
# Python 2.7.6 (default, Jun 22 2015, 17:58:13)  [GCC 4.8.2] on linux2
# Python 3.4.3 (default, Oct 14 2015, 20:28:29)  [GCC 4.8.4] on linux

import collections

Color = collections.namedtuple('Color', ['r', 'g', 'b'])
red = Color(r=256, g=0, b=0)

# Access the namedtuple as a dict
print(red.__dict__['r'])  # 256

# Drop the namedtuple only keeping the dict
red = red.__dict__
print(red['r'])  #256

Seeing as dict is the semantic way to get a dictionary representing soemthing, (at least to the best of my knowledge).


It would be nice to accumulate a table of major python versions and platforms and their support for __dict__, currently I only have one platform version and two python versions as posted above.

| Platform                      | PyVer     | __dict__ | _asdict |
| --------------------------    | --------- | -------- | ------- |
| Ubuntu 14.04 LTS              | Python2.7 | yes      | yes     |
| Ubuntu 14.04 LTS              | Python3.4 | yes      | yes     |
| CentOS Linux release 7.4.1708 | Python2.7 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.4 | no       | yes     |
| CentOS Linux release 7.4.1708 | Python3.6 | no       | yes     |

回答 3

案例1:一维元组

TUPLE_ROLES = (
    (912,"Role 21"),
    (913,"Role 22"),
    (925,"Role 23"),
    (918,"Role 24"),
)


TUPLE_ROLES[912]  #==> Error because it is out of bounce. 
TUPLE_ROLES[  2]  #==> will show Role 23.
DICT1_ROLE = {k:v for k, v in TUPLE_ROLES }
DICT1_ROLE[925] # will display "Role 23" 

情况2:二维元组
示例:DICT_ROLES [961]#将显示“后端编程器”

NAMEDTUPLE_ROLES = (
    ('Company', ( 
            ( 111, 'Owner/CEO/President'), 
            ( 113, 'Manager'),
            ( 115, 'Receptionist'),
            ( 117, 'Marketer'),
            ( 119, 'Sales Person'),
            ( 121, 'Accountant'),
            ( 123, 'Director'),
            ( 125, 'Vice President'),
            ( 127, 'HR Specialist'),
            ( 141, 'System Operator'),
    )),
    ('Restaurant', ( 
            ( 211, 'Chef'), 
            ( 212, 'Waiter/Waitress'), 
    )),
    ('Oil Collector', ( 
            ( 211, 'Truck Driver'), 
            ( 213, 'Tank Installer'), 
            ( 217, 'Welder'),
            ( 218, 'In-house Handler'),
            ( 219, 'Dispatcher'),
    )),
    ('Information Technology', ( 
            ( 912, 'Server Administrator'),
            ( 914, 'Graphic Designer'),
            ( 916, 'Project Manager'),
            ( 918, 'Consultant'),
            ( 921, 'Business Logic Analyzer'),
            ( 923, 'Data Model Designer'),
            ( 951, 'Programmer'),
            ( 953, 'WEB Front-End Programmer'),
            ( 955, 'Android Programmer'),
            ( 957, 'iOS Programmer'),
            ( 961, 'Back-End Programmer'),
            ( 962, 'Fullstack Programmer'),
            ( 971, 'System Architect'),
    )),
)

#Thus, we need dictionary/set

T4 = {}
def main():
    for k, v in NAMEDTUPLE_ROLES:
        for k1, v1 in v:
            T4.update ( {k1:v1}  )
    print (T4[961]) # will display 'Back-End Programmer'
    # print (T4) # will display all list of dictionary

main()

Case #1: one dimension tuple

TUPLE_ROLES = (
    (912,"Role 21"),
    (913,"Role 22"),
    (925,"Role 23"),
    (918,"Role 24"),
)


TUPLE_ROLES[912]  #==> Error because it is out of bounce. 
TUPLE_ROLES[  2]  #==> will show Role 23.
DICT1_ROLE = {k:v for k, v in TUPLE_ROLES }
DICT1_ROLE[925] # will display "Role 23" 

Case #2: Two dimension tuple
Example: DICT_ROLES[961] # will show ‘Back-End Programmer’

NAMEDTUPLE_ROLES = (
    ('Company', ( 
            ( 111, 'Owner/CEO/President'), 
            ( 113, 'Manager'),
            ( 115, 'Receptionist'),
            ( 117, 'Marketer'),
            ( 119, 'Sales Person'),
            ( 121, 'Accountant'),
            ( 123, 'Director'),
            ( 125, 'Vice President'),
            ( 127, 'HR Specialist'),
            ( 141, 'System Operator'),
    )),
    ('Restaurant', ( 
            ( 211, 'Chef'), 
            ( 212, 'Waiter/Waitress'), 
    )),
    ('Oil Collector', ( 
            ( 211, 'Truck Driver'), 
            ( 213, 'Tank Installer'), 
            ( 217, 'Welder'),
            ( 218, 'In-house Handler'),
            ( 219, 'Dispatcher'),
    )),
    ('Information Technology', ( 
            ( 912, 'Server Administrator'),
            ( 914, 'Graphic Designer'),
            ( 916, 'Project Manager'),
            ( 918, 'Consultant'),
            ( 921, 'Business Logic Analyzer'),
            ( 923, 'Data Model Designer'),
            ( 951, 'Programmer'),
            ( 953, 'WEB Front-End Programmer'),
            ( 955, 'Android Programmer'),
            ( 957, 'iOS Programmer'),
            ( 961, 'Back-End Programmer'),
            ( 962, 'Fullstack Programmer'),
            ( 971, 'System Architect'),
    )),
)

#Thus, we need dictionary/set

T4 = {}
def main():
    for k, v in NAMEDTUPLE_ROLES:
        for k1, v1 in v:
            T4.update ( {k1:v1}  )
    print (T4[961]) # will display 'Back-End Programmer'
    # print (T4) # will display all list of dictionary

main()

回答 4

如果没有_asdict(),则可以使用以下方式:

def to_dict(model):
    new_dict = {}
    keys = model._fields
    index = 0
    for key in keys:
        new_dict[key] = model[index]
        index += 1

    return new_dict

if no _asdict(), you can use this way:

def to_dict(model):
    new_dict = {}
    keys = model._fields
    index = 0
    for key in keys:
        new_dict[key] = model[index]
        index += 1

    return new_dict

回答 5

Python 3.将任何字段分配给字典作为字典的必需索引,我使用了“名称”。

import collections

Town = collections.namedtuple("Town", "name population coordinates capital state_bird")

town_list = []

town_list.append(Town('Town 1', '10', '10.10', 'Capital 1', 'Turkey'))
town_list.append(Town('Town 2', '11', '11.11', 'Capital 2', 'Duck'))

town_dictionary = {t.name: t for t in town_list}

Python 3. Allocate any field to the dictionary as the required index for the dictionary, I used ‘name’.

import collections

Town = collections.namedtuple("Town", "name population coordinates capital state_bird")

town_list = []

town_list.append(Town('Town 1', '10', '10.10', 'Capital 1', 'Turkey'))
town_list.append(Town('Town 2', '11', '11.11', 'Capital 2', 'Duck'))

town_dictionary = {t.name: t for t in town_list}