Python:TypeError:不可散列的类型:'list'
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13675296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: TypeError: unhashable type: 'list'
提问by Keenan
I'm trying to take a file that looks like this
我正在尝试获取一个看起来像这样的文件
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
And use a dictionary to so that the output looks like this
并使用字典使输出看起来像这样
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
This is what I've tried
这是我试过的
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()
I keep getting a TypeError: unhashable type: 'list'. I know that keys in a dictionary can't be lists but I'm trying to make my value into a list not the key. I'm wondering if I made a mistake somewhere.
我不断得到一个TypeError: unhashable type: 'list'. 我知道字典中的键不能是列表,但我试图将我的值变成列表而不是键。我想知道我是否在某个地方犯了错误。
采纳答案by RocketDonkey
As indicated by the other answers, the error is to due to k = list[0:j], where your key is converted to a list. One thing you could try is reworking your code to take advantage of the splitfunction:
正如其他答案所示,错误是由于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']}
Note that if you are using Python 3.x, you'll have to make a minor adjustment to get it work properly. If you open the file with rb, you'll need to use line = line.split(b'x')(which makes sure you are splitting the byte with the proper type of string). You can also open the file using with open('filename.txt', 'rU') as f:(or even with open('filename.txt', 'r') as f:) and it should work fine.
请注意,如果您使用的是 Python 3.x,则必须稍作调整才能使其正常工作。如果您使用 来打开文件rb,则需要使用line = line.split(b'x')(这确保您使用正确类型的字符串拆分字节)。您还可以使用with open('filename.txt', 'rU') as f:(甚至with open('filename.txt', 'r') as f:)打开文件,它应该可以正常工作。
回答by Jesse the Game
You're trying to use k(which is a list) as a key for d. Lists are mutable and can't be used as dict keys.
您正在尝试使用k(这是一个列表)作为d. 列表是可变的,不能用作字典键。
Also, you're never initializing the lists in the dictionary, because of this line:
此外,由于这一行,您永远不会初始化字典中的列表:
if k not in d == False:
Which should be:
应该是:
if k not in d == True:
Which should actually be:
实际上应该是:
if k not in d:
回答by Andrew Clark
The TypeErroris happening because kis a list, since it is created using a slice from another list with the line k = list[0:j]. This should probably be something like k = ' '.join(list[0:j]), so you have a string instead.
该TypeError发生的事情,因为k是一个列表,因为它使用的是从片与另一行列表中创建k = list[0:j]。这可能应该类似于k = ' '.join(list[0:j]),所以你有一个字符串。
In addition to this, your ifstatement is incorrect as noted by Jesse's answer, which should read if k not in dor if not k in d(I prefer the latter).
除此之外,if正如杰西的回答所指出的那样,您的陈述是不正确的,应该阅读if k not in d或if not k in d(我更喜欢后者)。
You are also clearing your dictionary on each iteration since you have d = {}inside of your forloop.
由于您d = {}在for循环内部,因此您还在每次迭代时清除字典。
Note that you should also not be using listor fileas variable names, since you will be masking builtins.
请注意,您也不应该使用list或file作为变量名,因为您将屏蔽内置函数。
Here is how I would rewrite your code:
以下是我将如何重写您的代码:
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:]))
The dict.setdefault()method above replaces the if k not in dlogic from your code.
dict.setdefault()上面的方法替换了if k not in d代码中的逻辑。
回答by martineau
The reason you're getting the unhashable type: 'list'exception is because k = list[0:j]sets kto be a "slice" of the list, which is logically another, often shorter, list. What you need is to get just the first item in list, written like so k = list[0]. The same for v = list[j + 1:]which should just be v = list[2]for the third element of the list returned from the call to readline.split(" ").
您收到unhashable type: 'list'异常的原因是k = list[0:j]设置k为列表的“切片”,这在逻辑上是另一个通常较短的列表。你需要的是只得到列表中的第一项,像这样写k = list[0]。对于从调用返回的列表的第三个元素v = list[j + 1:]应该是相同的。v = list[2]readline.split(" ")
I noticed several other likely problems with the code, of which I'll mention a few. A big one is you don't want to (re)initialize dwith d = {}for each line read in the loop. Another is it's generally not a good idea to name variables the same as any of the built-ins types because it'll prevent you from being able to access one of them if you need it — and it's confusing to others who are used to the names designating one of these standard items. For that reason, you ought to rename your variable listvariable something different to avoid issues like that.
我注意到代码中还有其他几个可能的问题,我将提及其中的几个。一个大的一个是你不希望(重新)初始化d与d = {}每一行的循环中读取。另一个是将变量命名为与任何内置类型相同的名称通常不是一个好主意,因为它会阻止您在需要时访问它们中的一个 - 并且这会让习惯使用的其他人感到困惑指定这些标准项目之一的名称。出于这个原因,您应该将变量重命名为list不同的名称,以避免出现此类问题。
Here's a working version of your with these changes in it, I also simplified the ifstatement expression you had which checks to see if the key is already in the dictionary — there are even shorter implicit ways to do this sort of thing, but using a conditional statement is fine for now.
这是您的工作版本,其中包含这些更改,我还简化了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))
Output:
输出:
d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
回答by raton
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)
回答by All ?? Vаи?тy
Note:This answer does not explicitly answer the asked question. the other answers do it. Since the question is specific to a scenarioand the raised exception is general, This answer points to the general case.
注意:此答案并未明确回答所提出的问题。其他答案做到了。由于问题特定于某个场景并且引发的异常是 general,因此此答案指向一般情况。
Hash values are just integers which are used to compare dictionary keys during a dictionary lookup quickly.
哈希值只是用于在字典查找期间快速比较字典键的整数。
Internally, hash()method calls __hash__()method of an object which are set by default for any object.
在内部,hash()方法调用__hash__()对象的方法,默认情况下为任何对象设置。
Converting a nested list to a set
将嵌套列表转换为集合
>>> 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'
This happens because of the list inside a list which is a list which cannot be hashed. Which can be solved by converting the internal nested lists to a tuple,
发生这种情况是因为列表中的列表是无法散列的列表。这可以通过将内部嵌套列表转换为元组来解决,
>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])
Explicitly hashing a nested list
显式散列嵌套列表
>>> 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
The solution to avoid this error is to restructure the list to have nested tuples instead of lists.
避免此错误的解决方案是将列表重构为具有嵌套元组而不是列表。

