Search code examples
pythonsettuplescomparison

Comparison of integer against integer or presence in a set or tuple


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', ...

Solution

  • 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