1

From what I have researched most operators and methods can be overridden when creating a class in python. By using __add__(self, other) and others for example.

My "problem" (more like I don't quite understand how it is done) is for verifying is something is in my class I have to obviously use __contains__(self, theThing). Alas I thought this should return a boolean value in the code itself, but from example code I have seen, like this:

def __contains__(self, posORname):
     return [node.getId() for node in self.tree if node.getId() == posORname or node.getName() == posORname]

What I am returning is therefore a tuple containing the Id of where said item is. Could someone explain why this is done instead of returning True or False? And if so, shouldn't it be implicitly possible to get the index of an item in a structure by just using in?

Thanks :D

rafaelc
  • 57,686
  • 15
  • 58
  • 82
Mixone
  • 1,327
  • 1
  • 13
  • 24
  • Is you goal to find if a class has a specific attribute? Why not attempt to call the attribute and then handle an `AttributeError` exception when it doesn't exist? – ODiogoSilva May 02 '15 at 18:49
  • Its rather I am working with a tree as Abstract Data Type, with "n" children for each node, and therefore instead of having to create a function like: def myTreeContains(self, value) I would like to be able to just call this with an "in", like so: `thisTree = Tree() if "Harry" in thisTree: print("Harry is in the tree")` – Mixone May 02 '15 at 18:53
  • That a rather odd looking `__contains__` method. `return any(posOrName in [node.getId() or node.getName()] for node in self.tree)` would be sufficient. Generally speaking, the contexts where `__contains__` is used will just look at the boolean value of the list it is returning (empty `False`, non-empty `True`), so it's not incorrect but it is doing far more work than necessary. – chepner May 02 '15 at 19:07
  • ah, I see what you mean, so in short this is just overly complicating it and it basically is True False, thanks :D – Mixone May 02 '15 at 20:23

3 Answers3

1

__contains__() is expected to return a boolean value. In your case, __contains__() is returning a list with any tree nodes that match posORname. Thus, it's basically just a lazy way of implementing __contains__(), because in a boolean context:

  1. An empty list is equivalent to False.
  2. A non-empty list is equivalent to True.

While you could potentially have __contains__() return a data structure with the index or ID of the matching tree node, the in operator doesn't care; it only exists to check whether or not an item is contained by an object. Also, __contains__() is not intended to be called directly, so relying on it to return such information would be an abuse of the __contains__() method.

Instead, you would be better off implementing an separate method for getting the index/id of a node.

Community
  • 1
  • 1
cyfur01
  • 3,262
  • 1
  • 34
  • 38
1

The result of __contains__ is converted to a boolean according to the usual rules, so that, e.g., empty lists count as False while lists with something in them count as True. So for your example, if the list has anything in it --- that is, any items match the criteria in that list comprehension --- then the in test will be True.

This auto-conversion-to-bool behavior does not appear to be explicitly documented, and is different from other operators (like < and >), which return what they return without converting to bool. There is some discussion of the behavior here.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
1

For python2 __contains__ or python3 __contains__ both should return true or false. And now the question is what is True and what is False. Truth value testing.

The following values are considered false:

  • None
  • False
  • zero of any numeric type, for example, 0, 0.0, 0j.
  • any empty sequence, for example, '', (), [].
  • any empty mapping, for example, {}.
  • instances of user-defined classes, if the class defines a bool() or len() method, when that method returns the integer zero or bool value False.
Yeo
  • 11,416
  • 6
  • 63
  • 90
  • Thanks :D I think I will maybe create a dynamic variable in the namespace of the class for storing the id of the most recent '__contains()__' call thanks for the info and link :D – Mixone May 02 '15 at 20:25