Search code examples
pythonpsychopy

Unhashable types & replacing inputs


The goal is simple: show a dialog with options, then when a option is selected it will automatically replace some values (to decrease the possibility of making an error while typing the values manually). The following code is part of a larger code, but this is the most important part. The larger piece of code was written by someone else. I wrote the following block:

if expInfo2['quadrant'] == 'UL':
        expInfo['refOrientation':'45','x':'-4.24','y':'4.24']
    elif expInfo2['quadrant'] == 'LL':
        expInfo['refOrientation':'-45','x':'-4.24','y':'-4.24']
    elif expInfo2['quadrant'] == 'UR':
        expInfo['refOrientation':'-45','x':'4.24','y':'4.24']
    elif expInfo2['quadrant'] == 'LR':
        expInfo['refOrientation':'45','x':'4.24','y':'-4.24']

The code works fine until it reads the second line, and gives the following error:

Traceback (most recent call last): File "D:\User\File\Experiment.py", line 48, in <module> expInfo['refOrientation':'45','x':'-4.24','y':'4.24'] TypeError: unhashable type ()

My experience with programming is limited, but I understand that the things I put in that second line do not fit together. However, I was thinking of splitting them piece by piece but I do not think that will work, like in the following:

if expInfo2['quadrant'] == 'UL':
    expInfo['refOrientation':'45']
    expInfo['x':'-4.24']
    expInfo['y':'4.24']
et cetera...

The full code:

#present a dialogue to chose lab room and whether eyetracker is on or not
expInfo2 = {'lab':'2','eyetracker': '0','quadrant':''}
dlg = gui.Dlg(title="Info", pos=(200, 400))
dlg.addField('Which lab are you in? 2 for lab-2, 3 for lab-3',expInfo2['eyelab'])
dlg.addField('Do you want the eyetracker on? 0 for yes, 1 for no',expInfo2['eyetracker'])
dlg.addField('What quadrant is used? UL=Upper Left, LL=Lower Left, UR=Upper Right, LR=Lower Right',expInfo2['quadrant'])
inf = dlg.show()

expInfo2['lab']=inf[0]
expInfo2['eyetracker'] = inf[1]
expInfo2['quadrant'] = inf[2]

############################## THIS IS THE CODE FOR LAB 2 ###########################################
if expInfo2['lab'] == '2':


    expInfo = {'observer':'insert','typeofstaircase':'insert','refOrientation':'','startorient':'insert','x':'','y':'','numstair':4,}
    dateStr = time.strftime("%b_%d_%H%M", time.localtime())#add the current time

    if expInfo2['quadrant'] == 'UL':
        expInfo['refOrientation':'45','x':'-4.24','y':'4.24']
    elif expInfo2['quadrant'] == 'LL':
        expInfo['refOrientation':'-45','x':'-4.24','y':'-4.24']
    elif expInfo2['quadrant'] == 'UR':
        expInfo['refOrientation':'-45','x':'4.24','y':'4.24']
    elif expInfo2['quadrant'] == 'LR':
        expInfo['refOrientation':'45','x':'4.24','y':'-4.24']

    #present a dialogue to change params
    dlg = gui.Dlg(title="Info", pos=(200, 400))
    dlg.addField('Observer:',expInfo['observer'])
    dlg.addField('Type of staircase?', expInfo['typeofstaircase'])
    dlg.addField('Start Orientation Increment:',expInfo['startorient'])
    dlg.addField('X:',expInfo['x'])
    dlg.addField('Y:',expInfo['y'])
    dlg.addField('Ref. Orienation:',expInfo['refOrientation'])
    #dlg.addField('Number of Staircases',expInfo['numstair'])
    inf = dlg.show()

    expInfo['observer']=inf[0]
    expInfo['typeofstaircase'] = inf[1]
    expInfo['startorient']=inf[2]
    expInfo['x']=inf[3]
    expInfo['y']=inf[4]
    expInfo['refOrientation']=inf[5]
    #expInfo['numstair'] = inf[6]
    #dlg = gui.DlgFromDict(expInfo, title='info', fixed=['date'])
    #if dlg.OK:
    #    print(expInfo)
    #else:
    #    core.quit()#the user hit cancel so exit

Any suggestions?


Solution

  • expInfo['refOrientation':'-45','x':'-4.24','y':'-4.24']
    

    So this is interpreted as

    expInfo.__getitem__((
       slice('refOrientation', '-45', None),
       slice('x', '-4.24', None),
       slice('y', '-4.24', None)
    ))
    

    , a 3-tuple of slice objects. expInfo is a dictionary, and only takes hashable types and

    hash((
       slice('refOrientation', '-45', None),
       slice('x', '-4.24', None),
       slice('y', '-4.24', None)
    ))
    

    raises the error

     TypeError: unhashable type: 'slice'
    

    because, well, they aren't hashable. It's very, very weird to use strings in slices like that so I don't think you are inputting the key in the correct way.


    I think what you are trying to do is update the dictionary. To do this you want:

    if expInfo2['quadrant'] == 'UL':
        expInfo.update({'refOrientation': '45', 'x': '-4.24', 'y': '4.24'})
    elif expInfo2['quadrant'] == 'LL':
        ...
    

    (note the whitespace I put in to make it more readable. I'd advise reading PEP8 before going any further with python since you throw the style guide out the window).