0

I had an issue where I tried to compare a variable of type integer to two other integers using an or, and did not realise that could not be done.

Original code

model = 4004

if model == 3002 or 3003:
    print("model be 300X")

elif model == 4004 or 4003:
    print("model be 400X")

else:
    print("model type not covered")

Returns

300X #when it should be 400X.

I have two other workarounds, neither of which look pythonic to me, but they work.

Is there a better way to do this?

Working Code

import itertools

model = 4004

if model in (3002, 3003):
    print("model be 300X")
    cycle_dict = {x: z for x, z in zip(range(1, 1001, 1), itertools.cycle(["C", "C", "A", "A", "B", "B"]))}
elif model in (4004, 4003):
    print("model be 400X")
    cycle_dict = {x: z for x, z in zip(range(1, 2001, 1), itertools.cycle(["C", "C", "C", "C", "A", "A", "A", "A", "B", "B", "B", "B"]))}
else:
    print("model type not covered")


if model == 3002:
    print("this is a 3002")
    cycle_dict = {x: z for x, z in zip(range(1, 1001, 1), itertools.cycle(["C", "C", "A", "A", "B", "B"]))}
if model == 3003:
    print("this is a 3003")
    cycle_dict = {x: z for x, z in zip(range(1, 1001, 1), itertools.cycle(["C", "C", "A", "A", "B", "B"]))}
if model == 4004:
    print("this is a 4004")
    cycle_dict = {x: z for x, z in zip(range(1, 2001, 1), itertools.cycle(["C", "C", "C", "C", "A", "A", "A", "A", "B", "B", "B", "B"]))}
if model == 4003:
    print("this is a 4003")
    cycle_dict = {x: z for x, z in zip(range(1, 2001, 1), itertools.cycle(["C", "C", "C", "C", "A", "A", "A", "A", "B", "B", "B", "B"]))}

print("cycle_dict : ", cycle_dict)

It returns a dictionary

cycle_dict :  {1: 'C', 2: 'C', 3: 'C', 4: 'C', 5: 'A', 6: 'A', 7: 'A', 8: 'A', 9: 'B', 10: 'B', 11: 'B', 12: 'B', ...
Windy71
  • 851
  • 1
  • 9
  • 30
  • What *issue* did you have when you tried to do that? What is wrong with the first approach you showed us? Seems fine to me. What do you visualise a pythonic answer to look like? – Reti43 Sep 15 '21 at 09:28
  • d = {3002: 0, 3003:0, 4004: 1000, 4003: 1000} then zip(range(1, d[model] + 1001, 1). Or you can do f = 1000 if model > 3999 else 0 and zip(range(1, f + 1001, 1) ( or zip(range(1, (1000 if model > 3999 else 0) + 1001, 1) – Yuri Sep 15 '21 at 09:30
  • I have added the original way I tried to do it – Windy71 Sep 15 '21 at 09:40
  • hi Reti43, both of my attempts work, they just look clunky (the logic side) and I don't know which method is better, a direct comparison against each possible type or to to check whether a model variant is within a tuple or set., I'm ok with the how the dict is made. – Windy71 Sep 15 '21 at 09:43

1 Answers1

1

Your initial attempt doesn't work because model == 3002 or 3003 is translated as (model == 3002) or 3003. The first condition is false, but 3003 is a truthy value. You needed to be explicit with model == 3002 or model == 3003.

>>> model = 4004
>>> model == 3002 or 3003
3003
>>> bool(model == 3002 or 3003)
True
>>> model == 3002 or model == 3003
False

Now, as for which method to use, I prefer

model in {a, b}

which is faster than a tuple, because the lookup time complexity is O(1). This barely matters if you have only a couple of checks, but it's something to keep in mind. Generally though value in tuple or value in set requires fewer keystrokes to type and its intention is clear.

Depending on your underlying logic, the following may be even better:

series = model // 1000
if series == 3:
    pass
elif series == 4:
    pass
Reti43
  • 9,656
  • 3
  • 28
  • 44
  • Thank you Reti, I had not realised model == 3002 or 3003 is translated as (model == 3002) or 3003, great answer and explanation, thank you. – Windy71 Sep 15 '21 at 11:06