0

I have an object a and a list, and i want to check if the object a is in that list. That means the same object with the same id. To compare a and a single item of that list i would us the is keyword, something like a is ls[0], not == because == would compare the values of the two and not if they are the same object. I know about the in keyword to see if a list contains a value but that compares values (similar to ==) and not objects.

Consider the following code:

class Foo(object):
  def __init__(self,value):
    self.value=value
  def __eq__(self,other):
    return True

a=Foo(0)
b=Foo(1)
if a is b:
  print("Error, a is b")
  exit()

ls=[b]
if b is not ls[0]:
  print("Error, b is not ls[0]")
  exit()

if a in ls:
  print("Don't print this line")
else:
  print("Print this line instead")

How can i change the if statement so that "Print this line instead" is printed?

Changing it to if a is in ls: or if a in is ls: gives a syntax error. And yes i know i can make a function like this:

def isIn(object,ls):
  for e in ls:
    if e is object:
      return True
  return False

But that looks clumsy, is there a nicer way?

1 Answers1

-4

CPython and PyPy do that already as a shortcut; i.e. when comparing for equality, they first check for identity. You can test that with the following code:

class Test:
    def __init__(self, name): self.name = name
    def __eq__(self, other): print(self, other); return False
    def __str__(self): return self.name


x = [Test(c) for c in 'abcdef']
print(x[2] in x)

The output shows that there is no c c equality comparison however the in check returns True:

a c
b c
True
a_guest
  • 34,165
  • 12
  • 64
  • 118
  • 2
    Thank you, but that is not the question. – 12431234123412341234123 Sep 03 '21 at 12:36
  • @12431234123412341234123 Then the real question is, why do you want to do that? – a_guest Sep 03 '21 at 12:38
  • 2
    I have a list of elements, i want to check if any of them is `None`. `==` shouldn't be used to check for `None` since there can be false positives, it is better to use `is`. – 12431234123412341234123 Sep 03 '21 at 12:41
  • @12431234123412341234123 Can you explain under what circumstances there will be false positives? I see your `Foo` example class but its implementation of `__eq__` is nonsensical so can you provide a real world example? It seems that either (a) your data model doesn't treat `None` as a special/sentinel value in which case you shouldn't put `None`s into your list in the first place but create a separate `sentinel = object()`, or (b) your data model is broken in some other way, e.g. via such a `Foo.__eq__` implementation. This all smells like an [XY problem](https://xyproblem.info/). – a_guest Sep 03 '21 at 18:44