Python:TypeError:不可用类型:'list'

时间:2012-12-02 23:49:21

标签: python list dictionary typeerror

我正在尝试使用看起来像这样的文件

AAA x 111
AAB x 111
AAA x 112
AAC x 123
...

使用字典使输出看起来像这样

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}

这就是我试过的

file = open("filename.txt", "r") 
readline = file.readline().rstrip()
while readline!= "":
    list = []
    list = readline.split(" ")
    j = list.index("x")
    k = list[0:j]
    v = list[j + 1:]
    d = {}
    if k not in d == False:
        d[k] = []
    d[k].append(v)
    readline = file.readline().rstrip()

我一直在TypeError: unhashable type: 'list'。我知道字典中的键不能是列表,但我试图将我的值变成列表而不是键。我想知道我是否在某处犯了错误。

6 个答案:

答案 0 :(得分:39)

正如其他答案所示,错误是由k = list[0:j]引起的,您的密钥将转换为列表。您可以尝试的一件事是重新编写代码以利用split函数:

# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
  d = {}
  # Here we use readlines() to split the file into a list where each element is a line
  for line in f.readlines():
    # Now we split the file on `x`, since the part before the x will be
    # the key and the part after the value
    line = line.split('x')
    # Take the line parts and strip out the spaces, assigning them to the variables
    # Once you get a bit more comfortable, this works as well:
    # key, value = [x.strip() for x in line] 
    key = line[0].strip()
    value = line[1].strip()
    # Now we check if the dictionary contains the key; if so, append the new value,
    # and if not, make a new list that contains the current value
    # (For future reference, this is a great place for a defaultdict :)
    if key in d:
      d[key].append(value)
    else:
      d[key] = [value]

print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

请注意,如果您使用的是Python 3.x,则必须进行微调以使其正常工作。如果使用rb打开文件,则需要使用line = line.split(b'x')(这样可以确保使用正确的字符串类型拆分字节)。您也可以使用with open('filename.txt', 'rU') as f:(甚至with open('filename.txt', 'r') as f:)打开文件,它应该可以正常工作。

答案 1 :(得分:14)

您尝试使用k(列表)作为d的密钥。列表是可变的,不能用作字典键。

此外,由于以下行,您永远不会初始化字典中的列表:

if k not in d == False:

应该是:

if k not in d == True:

实际应该是:

if k not in d:

答案 2 :(得分:10)

  

注意:   该答案没有明确回答所提问题。其他答案可以做到。由于问题是特定于情境的,而提出的例外是一般性的,因此该答案指向一般情况。

哈希值只是整数,用于在字典查找期间快速比较字典键。

内部,hash()方法调用对象的__hash__()方法,该方法默认情况下为任何对象设置。

嵌套列表转换为集合

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

发生这种情况是因为列表内的列表是不能散列的列表。可以通过将内部嵌套列表转换为元组

来解决
>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])

明确哈希嵌套列表

>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


>>> hash(tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> hash(tuple([1, 2, 3, tuple([4, 5,]), 6, 7]))
-7943504827826258506
  

避免此错误的解决方案是将列表重组为具有嵌套元组而不是列表。

答案 3 :(得分:4)

您获得unhashable type: 'list'例外的原因是因为k = list[0:j]k设置为列表的“切片”,这在逻辑上是另一个,通常更短的列表。你需要的只是获得列表中的第一项,如k = list[0]所示。对于从v = list[j + 1:]调用返回的列表的第三个元素,v = list[2]应该只有readline.split(" ")

我注意到代码中存在其他一些可能的问题,我将提到一些问题。对于循环中读取的每一行,您不希望(重新)使用d初始化d = {}。另一个是,将变量命名为与任何内置类型相同的通常不是一个好主意,因为它会阻止您在需要时访问其中一个 - 并且对于习惯于其中的其他人而言,这会让您感到困惑。指定其中一个标准项目的名称。出于这个原因,您应该将变量list变量重命名,以避免出现类似问题。

这是你的工作版本中的这些变化,我还简化了你所拥有的if语句表达式,它检查键是否已经存在于字典中 - 还有更短的隐式方法来执行此操作有点像,但现在使用条件语句就好了。

d = {}
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline:
    lst = readline.split(" ") # Split into sequence like ['AAA', 'x', '111'].
    k = lst[0]  # First item.
    v = lst[2]  # Third item.
    if k not in d:  # New key?
        d[k] = []  # Initialize its associated value to an empty list.
    d[k].append(v)
    readline = file.readline().rstrip()

file.close()  # Done reading file.
print('d: {}'.format(d))

输出:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

答案 4 :(得分:0)

TypeError正在发生,因为k是一个列表,因为它是使用来自另一个列表k = list[0:j]的切片创建的。这应该类似k = ' '.join(list[0:j]),所以你有一个字符串。

除此之外,您的if声明不正确,如Jesse的回答所述,该回复应为if k not in dif not k in d(我更喜欢后者)。

您还在每次迭代时清除字典,因为d = {}循环中有for

请注意,您也不应该使用listfile作为变量名称,因为您将屏蔽内置函数。

以下是我重写代码的方法:

d = {}
with open("filename.txt", "r") as input_file:
    for line in input_file:
        fields = line.split()
        j = fields.index("x")
        k = " ".join(fields[:j])
        d.setdefault(k, []).append(" ".join(fields[j+1:]))

上面的dict.setdefault()方法替换了代码中的if k not in d逻辑。

答案 5 :(得分:-1)

    python 3.2

    with open("d://test.txt") as f:
              k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines())
              d={}
              for i,_,v in k:
                      d.setdefault(i,[]).append(v)