2

I created the following list comprehension in python:

[int(a[0].internal_value).lower() if type(a[0].internal_value) in (str,unicode) and a[0].internal_value.isdigit() == True
 else str(a[0].internal_value).lower() if type(a[0].internal_value) in (str,unicode)
 else int(a[0].internal_value) if type(a[0].internal_value) in (float,int)
 for a in ws.iter_rows() if a[0].internal_value <> None]

I'm having issues trying to construct the final else, if condition:

else int(a[0].internal_value) if type(a[0].internal_value) in (float,int)

I get an invalid syntax if I use the if conditional in that line.

 if type(a[0].internal_value) in (float,int)

If I remove the if statement

else int(a[0].internal_value)

then it seems to run fine. I need to have that if statement in there.

To me the else, if conditions are list comprehensions way of doing the more simple if, else conditions:

if i == x:
  do something
elif i == y:
  do something
elif i == z:
  do something

By rule, you do not always have to have an 'else' to close a series of conditional sentences. It seems to me, that my code wants a final 'else' in the comprehension. Am I correct in stating that and if so, is there a way to construct a final else, if in a python list comprehension instead of a final else?

4
  • 2
    Note: <> has been deprecated in favour of !=; the deprecated operator has been removed from Python 3 altogether. Commented Oct 18, 2013 at 22:05
  • @Martijn. I'm running 2.7 Commented Oct 18, 2013 at 22:06
  • @Joran Beasley. You need to start somewhere with list comprehensions. Commented Oct 18, 2013 at 22:07
  • 1
    @Mike, starting is [ x*x for x in range(10) ], not this. Listen to Joran... Commented Oct 18, 2013 at 22:15

2 Answers 2

10

You are (ab)using conditional expressions, and they must be of the form true_expression if test else false_expression. These expressions always produce a value, unlike an if compound statement.

Note that you should not test for == True; boolean expressions are already true or false without that test. Don't use <> either, that operator has been deprecated and has removed from Python 3 altogether. When testing for None, a singleton, you'd use is not None however.

You are testing against type() results; that looks like you want to use isinstance() tests instead.

You are also using int() on values, then calling .lower() on the result. There is no int.lower() method, so those calls will fail with an AttributeError.

The following is closer to working just fine, unless there are more types than int, float, str or unicode:

[int(a[0].internal_value) if isinstance(a[0].internal_value, (float, int)) or a[0].internal_value.isdigit() 
 else str(a[0].internal_value).lower()
 for a in ws.iter_rows() if a[0].internal_value is not None]

However, I'd farm out the conversion to filter function instead:

def conversion(value):
    if isinstance(value, (float, int)):
        return int(value)
    return str(value).lower()

then use that in a list comprehension:

[conversion(a[0].internal_value) for a in ws.iter_rows() if a[0].internal_value is not None]
Sign up to request clarification or add additional context in comments.

3 Comments

yeah (I gave you +1 all the same) since that was a very good explanation if you actually for some reason wanted to do a list comprehension like that :P
@Martijn. Thanks for taking the time to work me through this. I'm using your code and doing some testing. I'll get back and let you know my results. Thanks!
@Martijn. Thanks that worked! I may have some more types to script around, but I think I can handle that in the function and call to the list comprehension. Very nice clear and concise answer!
2

It might be easier if you create an auxilary function to help you. I also removed == True and int().lower(). I don't think there's any benefit to cramming all the logic into the list comprehension, but that's up to you.

def helper(x):
    if type(x) in (str,unicode) and x.isdigit():
        return int(x)
    elif type(x) in (str,unicode):
        return str(x).lower()
    elif type(x) in (float,int):
        return int(x)

[helper(a[0].internal_value)
 for a in ws.iter_rows()
 if a[0].internal_value <> None]

1 Comment

@axblount. Thanks for that! Definitely resolves me problem and helps me understand when to properly use list comprehensions. I'm on a bit of a learning curve right now :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.