5

I'm sure there is a really simple answer to this but I can't find it after searching around for a while.

prefixes = "JKLMNOPQ"
suffix = "ack"

for letter in prefixes:
    if letter == "Q" or letter == "O":
        print letter + "u" + suffix
    else:
        print letter + suffix

The above code works perfectly, the condition on the if statement seems a bit long-winded so I tried:

if letter == "Q" or "O":

which is shorter but doesn't work. I worked out that it doesn't work because "O" is a boolean expression which will always be True and that it doesn't consider anything on the left side of "or".

I tried putting brackets around it like so:

if letter == ("Q" or "O"):

but that only matches Q and not O.

Is there any shorthand way of getting the code to work or do I have to use the long-winded way that's working for me?

FiveAlive
  • 305
  • 1
  • 2
  • 4
  • 1
    `("Q" or "O")` is the same as `Q` – onemach Jan 07 '12 at 08:03
  • 2
    Programming languages are *formal languages* with strictly defined meaning of any given syntax. You generally can't just decide that a given expression looks "long winded" and try shortening it as you would in English. It **is** appropriate to look at the code you're writing and wonder if there are any shorter or clearer ways of writing it, particularly while you're learning. But you need to do so with *understanding*, not just try random variations and see if they work. The worst result you could get is that it **does** work, because it will have worked by accident and might fail next time! – Ben Jan 07 '12 at 08:16

5 Answers5

8

Use one of the following solutions to implement the condition:

  • list: if letter in ['Q', 'O']
  • tuple: if letter in ('Q', 'O')
  • string: if letter in 'QO'

Update: For completeness: Regexp: re.match('[OQ]', letter) (copied from Paul Hankings answer (you should vote his anwer if you think regexp is THE solution) )

Community
  • 1
  • 1
gecco
  • 17,969
  • 11
  • 51
  • 68
4

You can use letter in 'OQ' or re.match('[OQ]', letter)

More thoroughly, I'd probably define a string of prefixes that should get the 'u'.

prefixes = 'JKLMNOPQ'
prefixes_taking_u = 'OQ'
suffix = 'ack'
for p in prefixes:
    u_part = 'u' if p in prefixes_taking_u else ''
    print p + u_part + suffix

In your code, letter == ("O" or "Q") first evaluates ("O" or "Q") ("O" isn't false, so the result is "O") and so this is the same as letter == "O".

Your other attempt, letter == "O" or "Q" first evaluates letter == "O" and if it's True, it gives the answer True otherwise it'll give the answer "Q".

You can find the documentation for how or works in the language reference.

1
if letter in ['Q', 'O']

btw, it's better not to focus on how your write the code.

iloahz
  • 4,491
  • 8
  • 23
  • 31
0

And one more variant (faster in case there are a lot of prefixes, not just two):

prefixes = frozenset('QO')
if letter in prefixes:
    #...
Roman Susi
  • 4,135
  • 2
  • 32
  • 47
0

The "in string" option is best, in this special case where the input is a single character. More generally, for a smallish number of possible values, "in tuple" is preferred to "in list", as recent Pythons will build the tuple at compile time, whereas the list is built at run time.

When there are many options, a set or frozenset can be built once, and interrogated multiple times quickly.

Regex approaches are more complicated and/or slower than the options canvassed above.

(1) re.match('[QO]', letter) can't compete with letter in 'QO'

(2) initially needs_u = re.compile('[QO]').match followed by needs_u(letter) is horrid compared with initial needs_u = set('QO') followed by letter in needs_u

John Machin
  • 81,303
  • 11
  • 141
  • 189