Greem666
Greem666

Reputation: 949

List comprehensions with multiple conditions

I know this subject has been touched on a few times already, but all the topics I inspected did not ask the question I am about to ask (I think). What is wrong with declaration below?

from string import ascii_letters, digits as letters, digits

combinations = [letter1 + letter2 + digit1 + digit2 for digit1 in digits if (digit1 % 2 == 0) for digit2 in digits if (digit2 % 2 == 0) for letter1 in letters if (letter1 != 'a') for letter2 in letters if (letter2 != 'A')]

print combinations[:500]

I keep on getting:

TypeError: not all arguments converted during string formatting

Would be great to know what I am doing wrong, since I could swear I am following proper syntax here...

Upvotes: 0

Views: 265

Answers (3)

holdenweb
holdenweb

Reputation: 37003

The problem here is that the digits you import is a string, and so each digit1 and digit2 is also a (single-character) string. This makes (for example) digit1 % 2 appear to be an attempt to use Python's string interpolation mechanism - it's a % operator with a string left-hand operand.

Because that operand contains no % signs, there is no marker to locate the insertion of the right-hand operand, 2, hence the rather incomprehensible error message.

You should also lay your code out rather better - long single lines don't work!

Upvotes: 0

Alex L
Alex L

Reputation: 1114

I see a few problems.

First of all, your import doesn't do what you think it does:

>>> from string import ascii_letters, digits as letters, digits
>>> letters
'0123456789'
>>> digits
'0123456789'

Try something like this instead?

>>> from string import ascii_letters as letters, digits as digits
>>> letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> digits
'0123456789'

Secondly, when you use the % operator on a number, it's mod, but when you use it on a string, it's the format operator. You're using it on a string, hence the mumble about string formatting. If you want it to be the mod operator, you have to int() the thing you're using it on.

int(digit1) % 2

Thirdly, I agree with the others who say this is not easy to read/understand. Writing it differently, using a loop or range or functional notation, or at least formatting it differently to make the structure more apparent, would be an improvement.

Hope this helps.

Upvotes: 2

mwchase
mwchase

Reputation: 811

You're trying to do integer mod on a string containing a digit. I guess wrap digitFOO % 2 == 0 like int(digitFOO) % 2 == 0.

As Chris_Rands points out, it still won't work properly because the imports are broken.

Upvotes: 0

Related Questions