27

I'm writing a class which encapsulates any arbitrary object, including simple types. I want the "is" keyword to operate on the encapsulated value, such as this behavior:

Wrapper(True) is True -> True
Wrapper(False) is True -> False
Wrapper(None) is None -> True
Wrapper(1) is 1 -> True

Is there any object method I can override to get this behavior?

Heinrich Schmetterling
  • 6,614
  • 11
  • 40
  • 56

4 Answers4

43

No. is, and, and or cannot be overloaded.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 5
    Is that in Python documentation anywhere? Can't find anything verifying this. – Heinrich Schmetterling Oct 22 '10 at 01:28
  • 8
    The only reference is their absence in §3.4 of the langref. http://docs.python.org/reference/datamodel.html#special-method-names – Ignacio Vazquez-Abrams Oct 22 '10 at 01:29
  • This answer is quite old. Is this still true for latest Python versions? – Fran Marzoa Mar 03 '16 at 14:42
  • 3
    @Fran: Yes. The behavior regarding these operators has not changed. – Ignacio Vazquez-Abrams Mar 03 '16 at 20:19
  • 2
    I think I know why `is` cannot be overriden. Dictionary look ups and set lookups use `is` for fast equality checking since `__eq__` is overridable and potentially really slow. If `is` behavior was overridable there would be no way to guarantee fast dictionary lookup which would be detrimental to python's performance. – Alejandro Sep 27 '17 at 00:59
  • python3 here: seems like `and` and `or` can be overloaded, with `__and__`, `__rand__`, `__or__`, `__ror__`. Type `dir(int)` in the console to convince yourself. **EDIT:** my bad, they overload `&` and `|`, not `and` and `or` – User9123 Dec 26 '17 at 13:49
  • @Alejandro how can `dict` and `set` lookup use `is`? if the key is, say a `str`, then each instance of the same string should match. in `dict` and `set` lookup, speed is achieved by hashing, after which a `__eq__` test is done – user3204459 Apr 20 '20 at 20:32
  • @user3204459 Good point. No way could `is` be used in dictionary lookups. I don't know why these can't be overloaded... – Alejandro Jun 24 '21 at 16:58
5

is itself cannot be overloaded, but you may be interested in other "Reflection" magic methods which may be suitable for your use case (since you are looking at this thread):

__instancecheck__(self, instance) Checks if an instance is an instance of the class you defined (e.g. isinstance(instance, class).

__subclasscheck__(self, subclass) Checks if a class subclasses the class you defined (e.g. issubclass(subclass, class)).

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
4

Generally, if you want to test equality in terms of value (if x is 1, or True, or None), you'd use the == operator anyway. If you want to use the is operator, you're generally testing if something is referring to something else, like list1 is list2.

If you want to define special behavior for ==, you can define __eq__ in your class definition.

Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
  • 1
    `x is 1` is dangerous, but `x is None` is perfectly fine. `True`, `False`, and `None` are [guaranteed to be singletons](https://stackoverflow.com/questions/27276610/boolean-identity-true-vs-is-true), and I *think* integers -5 through 257 are also statically allocated in CPython, but you might be able to create one of those integers that isn't `is` identical. – Nick T Feb 20 '19 at 01:38
-4

No. is, and, and or cannot be overloaded.

Indeed. I believe that keywords are reserved and cannot be overloaded or changed.

See: http://docs.python.org/2/reference/lexical_analysis.html#keywords

"The following identifiers are used as reserved words, or keywords of the language, and cannot be used as ordinary identifiers."

The list is: ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']

This list can be viewed through the command

keyword.kwlist

(Don't forget to import keyword first)

Also:

keyword.iskeyword('is')

Returns True


Update:

My answer was bad and I should feel bad.

I've messed with del myself. I don't know why I didn't notice that...

2nd try:

The following documentation provides a full list of customizable behavior on classes. This includes all the methods for overriding and overloading operators. 'is' is not included.

http://docs.python.org/2/reference/datamodel.html#special-method-names

Best I can do.

  • But `del` can be overloaded, e.g., you can overload `del x[i]` or `del x.attr`. The question is about whether the semantics can be altered, not the syntax. – Dietrich Epp Jul 03 '13 at 20:19
  • `in` can be directly overloaded. `as` can be partially overloaded, in a context manager. `import` and `for` can be indirectly overloaded. – Ignacio Vazquez-Abrams Jul 03 '13 at 20:34