how to put variable in python defaultdict call - python-3.x

In a python defaultdict object (like obj1), I can call obj1['hello','there'] and get item. but when the input list is variable (for example: input_list), how I can call obj1[input_list]?
when I call obj1[input_list], python raise this error:
TypeError: unhashable type: 'list'
when use obj1[*input_list], python returns:
SyntaxError: invalid syntax
So what is the correct way to put list as variable in defaultdict?

The error TypeError: unhashable type: 'list' states that list is not hashable, but a dict always needs a hashable key!
If you test my_normal_dict[2,3] you can see that it actually treats these two numbers as the tuple (2,3) because the error is KeyError: (2, 3), so you need to input a hashable iterable like a tuple.
For example, my_dict[tuple(my_list)] should work, as long as all the elements of the tuple itself are hashable!
Note though: If your list is large, it may be relevant that this needs to copy all elements into a tuple.

Related

AttributeError: 'int' object has no attribute 'pop'

When writing list inside tuple, getting error:
AttributeError: 'int' object has no attribute 'pop'
fruits=('apple','banana', ['kiwi','grapes'])
fruits[1].pop()
fruits[1].append('rice')
print(fruits)
I am getting:
str object has no attribute pop
which is what I was expecting since fruits[1] is 'banana' which is a string and strings do not have a pop method.
If you look at the next line you will run into a similar issue since strings also don't have an append method.
If you remove both of those lines you shouldn't have any errors with just the list inside of the tuple.
fruits = ('apple','banana', ['kiwi','grapes'])
print(fruits)
Your issue is coming from you trying to pop a string, in the second line of your code - not from adding a list in the tuple. Now as tuples are immutable in python, you will need to convert it into a list if you wish to start modyfing what is inside of it. A simple example using your code is below.
fruits=('apple','banana', ['kiwi','grapes'])
fruits_list = list(fruits)
fruits_list.pop(1)
fruits_list.insert(1, 'rice')
fruits = tuple(fruits_list)
print(fruits)
You can read more about it here: pop/remove items out of a python tuple

Getting TypeError: list indices must be integers when using list[:,colIndex] to get column data as list

I have a 2D list (a list of lists) and am trying to use the notation list[:,colIndex] to pull out a single column's data into another list, but I'm getting a TypeError: list indices must be integers error.
for example:
lst = [[1,2,3],[10,12,13]]
lst[:,0]
Returns:
Traceback (most recent call last):
File "<input>", line 2, in <module>
TypeError: list indices must be integers
I don't understand...
Edit:
Running this in Python 3.9 gives me:
TypeError: list indices must be integers or slices, not tuple
It would seem that the [:,colIndex] syntax isn't supported by lists and is available to numpy arrays only :(
However I can use: list(zip(*lst))[colIndex] instead from this answer https://stackoverflow.com/a/44360278/1733467

TypeError: type.__new__() argument 2 must be tuple, not str

I get the following error when I run the piece of code below. I can clearly print the value of *strs on screen, which appears as string. But, when I do type(*strs), it throws TypeError: type.__new__() argument 2 must be tuple, not str. Can someone explain this behaviour?
strs = ["flower","flood","flight"]
print(*strs)
print(type(strs))
print(type(*strs))
Output:
Traceback (most recent call last):
print(type(*strs))
TypeError: type.__new__() argument 2 must be tuple, not str
flower flood flight
<class 'list'>
Process finished with exit code 1
The asterix operator in '*strs' unpacks the iterms in 'strs', which is a series of three strings. Your code ran into trouble when it tried to send those strings to the type() command, where type() was initialized by its __ new__() magic method.
type() has two forms:
1.) type(object) where the 'object' is an instance of some class.
2.) type(name, bases, dictionary) where 'bases' is a tuple that itemizes base classes, and a dictionary that contains definitions of base classes.
In your code, the use of the unpacking operation, *strs, resulted in type() being sent three arguments, so it was expecting a name, a tuple, and a dictionary. What it, and then __ new()__ got was three strings: A name (it received 'flower'), then another string, "flood", where it wanted a tuple. Here python threw the error and never made it to the third string, 'flight'.
We can duplicate the error with:
print(type("a","b","c"))
We can also see that either one or three (but not two) arguments were expected, with:
print(type("a","b"))
while the following command works just fine:
print(type("a"))
If you want to see the type of each member of *strs, first let it unpack to a list, then iterate through that list, printing the type of each member as you go.
mylist = [*strs]
for elm in mylist:
print(type(elm))
Does this answer the question of what caused that behavior and the error?

what is the meaning of hashable in dict

why I cannot write this {names: heroes} inside the dictionary .when I did this
{{names: heroes} for names, heroes in zip(names, heroes)} an error occurred which is a type error saying unhashable dict. What does that mean?
nums={{names:heroes} for names, heroes in zip(names,heroes)}
print(nums)
Traceback (most recent call last):
File "C:/Users/ahmod/AppData/Local/Programs/Python/Python37-32/mim.py", line 7, in <module>
nums={{names:heroes} for names, heroes in zip(names,heroes)}
File "C:/Users/ahmod/AppData/Local/Programs/Python/Python37-32/mim.py", line 7, in <setcomp>
nums={{names:heroes} for names, heroes in zip(names,heroes)}
TypeError: unhashable type: 'dict'
{{names: heroes} for names, heroes in zip(names, heroes)}
This is a set comprehension -because you are using the {} curly braces. In a set, each element must be hashable. you are setting each elements in the set to {names: heroes} - which is a dict. So you are trying to make a set of dict.
But unfortunately, in python, dict is not hashable - since it's a mutable type.
So you can't do that.
Instead you can try to create a dictionary directly:
{name: heroe for name, heroe in zip(names, heroes)}
By just removing the extra curly braces.

Why can't I sort a list of dicts in 3.x? Why do I get "TypeError: '<' not supported between instances of 'dict' and 'dict'"?

I had a perfectly functioning sort by value in python 2.7 but I'm trying to upgrade to python 3.6 and I get that error:
TypeError: '<' not supported between instances of 'dict' and 'dict'
Here is my code
server_list = []
for server in res["aggregations"]["hostname"]["buckets"]:
temp_obj = []
temp_obj.append({"name":server.key})
temp_obj.append({"stat": server["last_log"]["hits"]["hits"][0]["_source"][system].stat})
server_list.append(temp_obj)
server_list.sort(key=lambda x: x[0], reverse=False)
Why it's considered as a dict when I declare my server_list as a list. How can I make it sort by my name attribute?
Python 2's dictionary sort order was quite involved and poorly understood. It only happened to work because Python 2 tried to make everything orderable.
For your specific case, with {'name': ...} dictionaries with a single key, the ordering was determined by the value for that single key.
In Python 3, where dictionaries are no longer orderable (together with many other types), just use that value as the sorting key:
server_list.sort(key=lambda x: x[0]['name'], reverse=False)

Resources