TypeError: unhashable type: 'dict'

Hello,

Here is my error: TypeError: unhashable type: 'dict'

Here is the source that is used to handle such an output error:

# More Ideas...
    if state == "0":
        servos.add_servo = {
                        'Angle_0': {
                        {'name':'1a', 'servo_no':0, 'max_angle':0},
                        {'name':'1b', 'servo_no':1, 'max_angle':0},
                        {'name':'2c', 'servo_no':3, 'max_angle':0},
                        {'name':'2d', 'servo_no':4, 'max_angle':0},
                        {'name':'3e', 'servo_no':6, 'max_angle':0},
                        {'name':'3f', 'servo_no':7, 'max_angle':0},
                        {'name':'4g', 'servo_no':9, 'max_angle':0},
                        {'name':'4h', 'servo_no':10, 'max_angle':0}}}

I did find some ideas online but I do not think they are suited for my particular case and exercise.

Also…here is the file that creates the function that is used to handle the call to add_servo.

def add_servo(self, name, servo_no, max_angle):
        assert servo_no in range(0, 16)
        self.servos[name] = Servo(servo_no, max_angle)

I think I know what I am doing that is incorrect and I will test it soon. If anyone sees the error that programs in python3 more than I, please do jump forward and describe to me what it is I am doing that is faulty.

I sure could use some pointers. The reason I am using a dictionary is b/c of the changeable uses.

Seth

P.S. If anyone needs more info. b/c of my situation, please let me know. Also, I tried to make a dictionary in the global workspace before calling it in my server function application like so:

Angle_a: {
    'name':'1a', 'servo_no':0, 'max_angle':0}
Angle_b: {
    'name':'1b', 'servo_no':1, 'max_angle':0}
Angle_c: {
    'name':'2c', 'servo_no':3, 'max_angle':0}
Angle_d: {
    'name':'2d', 'servo_no':4, 'max_angle':0}
Angle_e: {
    'name':'3e', 'servo_no':6, 'max_angle':0}
Angle_f: {
    'name':'3f', 'servo_no':7, 'max_angle':0}
Angle_g: {
    'name':'4g', 'servo_no':9, 'max_angle':0}
Angle_g: {
    'name':'4h', 'servo_no':10, 'max_angle':0}

Servo_Angles = {
    "Angle_a":Angle_a,
    "Angle_b":Angle_b,
    "Angle_c":Angle_c,
    "Angle_d":Angle_d,
    "Angle_e":Angle_e,
    "Angle_f":Angle_f,
    "Angle_g":Angle_g,
    "Angle_h":Angle_h
}

That has not worked so far, i.e. as the output states: "Angle_a":Angle_a, NameError: name 'Angle_a' is not defined . I was unaware of having to define dictionaries prior to the call before using them in source code. I will try that too.

This means that you’re using an unhashable value as a key in a dict or
set. Keys need to be hashable for these to work because fast lookup is
based on dividing values into small “buckets”, each of which contains
very few values (ideally just 0 or 1 value). The distribution of values
is based on the hash function of the key.

In order for dictionary lookup to work later, the hash function of the
key needs to produce the same value when you do the lookup as it did
when the value was first wtored in the dictionary.

For this reason, not all things are suitable as keys: only hashable
things. Hashable items guarrentee that they hash function is stable.

Numbers are hashable, strings are hashable, tuples are hashable (because
a tupple is readonly and cannot be modified). You can make hashable
classes of your own at need.

Most mutable things such as dicts are not hashable.

The TypeError you are getting means that the type of object you’re
trying to use as a key is not hashable.

You have not supplied enough information to help further.

Normally an exception will be accompanied by a complete traceback
showing the line where the error occurred and the lines it was called
from. Please always include a full traceback with queries like this.

Cheers,
Cameron Simpson cs@cskk.id.au

2 Likes

Hello,

Thank you for the explanation. @cameron , I will get the traceback soon. Thank you for telling me about how to make others understand how to be assistive more when I make posts.

Seth

P.S.

When you state, as it did when the value was first stored in the dictionary, does this mean that File_A that gets called by File_B as an from File_A import * needs to have the dictionary in question?

Or…can I make the dictionary object in File_B and use it in File_B w/out it being in File_A?

@cameron , hello. I got the traceback after fixing the issue w/ the second portion of the source I provided:

 * Serving Flask app 'pwmsTwo'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.1.7:5000
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 354-274-358
192.168.7.1 - - [30/Oct/2022 04:59:38] "GET / HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:38] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:40] "GET /0 HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:41] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:49] "GET /50 HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 2548, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.handle_exception(e)
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/debian/.local/lib/python3.9/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/home/debian/Use_Servo/Servos/pwmsTwo.py", line 73, in updates
    '50_Percent': {
TypeError: unhashable type: 'dict'
192.168.7.1 - - [30/Oct/2022 04:59:49] "GET /50?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 304 -
192.168.7.1 - - [30/Oct/2022 04:59:49] "GET /50?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 304 -
192.168.7.1 - - [30/Oct/2022 04:59:49] "GET /50?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 304 -
192.168.7.1 - - [30/Oct/2022 04:59:52] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:54] "GET /0 HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:54] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:58] "GET /0 HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 04:59:58] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 05:00:01] "GET /start HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 05:00:01] "GET /favicon.ico HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 05:00:02] "GET /0 HTTP/1.1" 200 -
192.168.7.1 - - [30/Oct/2022 05:00:02] "GET /favicon.ico HTTP/1.1" 200 -

That is my debian distro obviously. I am on a 32-bit armhf machine for now for altering servos and putting them on a server just for reference.

When you state, as it did when the value was first stored in the dictionary, does this mean that File_A that gets called by File_B as an from File_A import * needs to have the dictionary in question?

No.

Or…can I make the dictionary object in File_B and use it in
File_B w/out it being in File_A?

Yes.

What I mean is: you store a value in a dictionary like this:

 d['a'] = 3

Here, the string 'a' is the key, and strings are hashable objects.
Hash table lookups are fast because a lookup goes to the internal bucket
used to store the value, and the bucket is selected by the hash
function.

When you look up a dictionary:

 x = d['a']

the lookup looks only in the bucket where we expect to find the value
for 'a' if it’s present. Again, we pick the bucket to examine from the
hash function of the key.

That’s what I mean about the hash function needing to be stable, and the
same when we stored the value and when we retrieve it. If the hash
function produces a different hash, we’ll look in the wrong bucket and
not find the value.

So, for immutable things like strings and numbers the hash function
value is stable because the string or number never changes. But most
mutable things do not have hash functions because their contents change.
This prevents them being used by accident as dict keys.

Cheers,
Cameron Simpson cs@cskk.id.au

2 Likes

Hello @cameron ,

Okay. Thank you for making me understand. I will keep this in mind when typing up the correct source code in File_A to be used in File_B.

Seth

The code in your first piece shown would produce the same error when the if branch gets executed.

    if state == "0":
        servos.add_servo = {
                        'Angle_0': {
#                                  ^--- Here you start a set.
                        {'name':'1a', 'servo_no':0, 'max_angle':0},
#                       ^--- This set item is a dict. Which is not possible.
#                       ...
                        {'name':'4h', 'servo_no':10, 'max_angle':0}}}
1 Like

Hello @vbrozik ,

You are right. It is the same error. I am learning now how to account for File_A dictionaries and then use them in File_B now. I am nowhere close to complete but the source code is moving forward, i.e. in some manner.

Seth

When I looked at your code again I think you first need to do some simpler exercises with the basic data types (tuple, list, dict, set) to get better understanding about how to use them.

Your data structure can probably use a list or tuple instead of a set. Or maybe it needs a complete redesign.


I am not sure if you are aware what does this code of yours do:

Angle_a: {
    'name':'1a', 'servo_no':0, 'max_angle':0}

It just declares the name Angle_a to have an annotation {'name': '1a', 'servo_no': 0, 'max_angle': 0}

The name Angle_a will not be defined at execution time:

>>> Angle_a: {
...     'name':'1a', 'servo_no':0, 'max_angle':0}
>>> Angle_a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Angle_a' is not defined

Annotations in Python are being used almost exclusively as type annotations. That annotation is an invalid type annotation.

Hello @vbrozik ,

Seth here again. I declared the variable and assigned it to Angle_a as Angle_a = 0.

In my library source code, I added the function in which I thought would be helpful but has proved unimportant and not working. Please see below:

class SrvoCtrl:
     def add_servo(self, name, servo_no, max_angle):
        assert servo_no in range(0, 16)
        self.servos[name] = Servo(servo_no, max_angle)
        self.servos[name].min_value = int(0.001 / self.bit_time)
        self.servos[name].max_value = int(0.002 / self.bit_time)

    def ListOne(self, nn):
        for n in nn:
            self.add_servo = {n['name'], n['channel'], n['max_angle']}
            Servo_Angles = {
                Angle_a = {
                'name': '1a', 'channel':0, 'max_angle':90},
                Angle_b = {
                'name':'1b', 'channel':1, 'max_angle':90},
                Angle_c = {
                'name':'2c', 'channel':3, 'max_angle':90},
                Angle_d = {
                'name':'2d', 'channel':4, 'max_angle':90},
                Angle_e = {
                'name':'3e', 'channel':6, 'max_angle':90},
                Angle_f = {
                'name':'3f', 'channel':7, 'max_angle':90},
                Angle_g = {
                'name':'4g', 'channel':9, 'max_angle':90},
                Angle_h = {
                'name':'4h', 'channel':10, 'max_angle':90}}

There are other parts to the source code in the lib. but the source is primarily for talking directly to a PCA9685 and handling PWM/GPIO I/O.

This is as far as I can go for now and I will read up on how dictionaries work w/ sets. Thank you.

I was trying to better use dictionaries w/ a changeable variable so I can alter source from a server midstream.

Seth

P.S. Thank you again for describing to me what exactly my source does. I will keep this in mind when reviewing tutorials and the python.org docs.

What is the variable declaration good for? Python has no declarations. In standard Python you can only declare types of variables for static type checking. They do not have impact during the program execution.

In your program you are not using type checking so you should not use the annotation constructs: variable_name: variable_annotation

This code is invalid (try to execute it):

            Servo_Angles = {
                Angle_a = {
                'name': '1a', 'channel':0, 'max_angle':90},
#               ...
                Angle_h = {
                'name':'4h', 'channel':10, 'max_angle':90}}

You cannot have statements (here assignment statements like Angle_a = ...) inside a set literal.

1 Like

Hello,

I understand now! Phew, it was hard to understand what was failing and why it was failing b/c I was listening to a tutorial at w3schools and they had that listed as a current tutorial.

But, I then proceeded to see the output of it. It was something unfamiliar and unhelpful to my source code.

Seth

P.S. I have changed things a bit. I will keep you updated if it is of any help to others in my situation!

@vbrozik and @cameron ,

Thank you two for trying to make me understand. I am learning more in time. The main issue was not related to me or my source code but the amperage of the power supply not allowing enough current to transpire into the motors in question.

I know what the source code I had stated means…

  1. Does not work.
  2. Not well researched.
  3. and oblivious to how the lack of my print functions would have helped outside of just jumping straight into a server before testing everything.

So, when I post next, it should be better thought out and better tested. Thank you both for trying to help when I could not located the root cause of my concerns w/ my current configuration(s).

Seth

P.S. Where there is a will, there is a way.