Search code examples
pythonpython-3.xbuilt-in

I have problem with one-line if else statement


This is mystery problem that occurres, I have dictionary here and try to iterate through it and create a new dict:

myDict = {(i,j):(i,j,i+j) if i != j else (i,2*i,3*i,4*i) for i in range(1,7) for j in range(1,7)}

newDict = {}
for i,j in myDict.items():
    for jj in j:
        newDict[jj]=[i] if jj not in newDict.keys() else newDict[jj].append(i)

but it stops in third cycle and face this error:

AttributeError: 'NoneType' object has no attribute 'append'

but when ever change the if else statement to this code:

newDict = {}
for i,j in myDict.items():
    for jj in j:
        if jj not in newDict .keys():
            newDict[jj]=[i]
        else:
            newDict[jj].append(i)

This code block works fine, but I dont know what's the problem with first code block.


Solution

  • As @Sayse has already nicely pointed out that 'append' is an inplace operation and it returns nothing ('None') after adding to list.

    Explanation of cause of error

    You are assigning in the if condition part of the condition expression, which means that in the subsequent else (or elif) whatever is computed is going to be assigned as well. So in this case else will be computed and it will be assigned to newDict[jj].

    So what is happening that for the first iteration of i your if condition is getting satisfied so it is adding to the dict. When i is equal to 2 then the else is coming into picture. So append is happening but remember append will return None. That's why it is adding None to key 1, 2 and 3 of NewDict from i=2 onwards. Once None is already there, when the iteration 3 (i=3) is starting then you can not add anything to None and that's why you are getting error in 3rd cycle. However when you are not doing conditional expression syntax, it will work fine.

    How to correct it (if you want to stick to one line conditional expression)

    You can use the below code to make sure that the else is computed with alternate syntax. Please notice the subtle difference.

    myDict = {(i,j):(i,j,i+j) if i != j else (i,2*i,3*i,4*i) for i in range(1,7) for j in range(1,7)}
    
    newDict = {}
    for i,j in myDict.items():
        for jj in j:
            newDict[jj]=[i] if jj not in newDict.keys() else newDict[jj]+[i]
    print(newDict)
    

    The print command gives me the following. Not sure if this is correct! Is this what you wanted?

    enter image description here