2

What is the right way to compare if a variable contains a callable I want? Should I use the is operator or the == operator?

In the following interactive session, I define two callables, f and g. I assign one to variable a and another to variable b.

Now, when I want to check if a is same as f or not, both a == f and a is f work.

>>> def f():
...     pass
...
>>> def g():
...     pass
...
>>> a = f
>>> b = g
>>> a == f
True
>>> a is f
True
>>> a == g
False
>>> a is g
False
>>> b == f
False
>>> b is f
False
>>> b == g
True
>>> b is g
True

My questions.

  1. Is using one operator better than the other?
  2. Is there a situation where one operator would produce a different result than the other?
Lone Learner
  • 18,088
  • 20
  • 102
  • 200
  • I don't see anything in the question linked as duplicate that answers my question. – Lone Learner Mar 09 '14 at 11:23
  • @LoneLearner: it tells you that function objects are only equal if they are the same object. It tells you why `f == g` is true only if `f is g` is true. – Martijn Pieters Mar 09 '14 at 11:25
  • 1
    @LoneLearner: What part of *is true only if* is unclear here? – Martijn Pieters Mar 09 '14 at 11:28
  • @LoneLearner: if you wanted to know about that in a context **other than functions** you did not make that clear. – Martijn Pieters Mar 09 '14 at 11:29
  • @LoneLearner: you just expanded your question to methods, which is a *different issue altogether*. – Martijn Pieters Mar 09 '14 at 11:32
  • I voted to close, yet I upvoted you ;). If what you ask is not the same with that post, make it clear plz. You could edit you yourselves' answer to a question, and then will get votes to reopen ;) – zhangxaochen Mar 09 '14 at 11:56
  • Given the number of border cases already underlined by others below and above, I would only write code that depend on function equality if I can control that equality, i.e. I would define a class instead of a function, put the executable code in `__call__` and my concept of equality in `__eq__`. In that situation `==`returns another result than `is`. Hmmm, that sounds like a lot of boiler plate, so I guess I'd rather try not to need function equality in the first place actually.  – Svend Mar 09 '14 at 11:57

1 Answers1

4

Two functions are only equal if they are the same object.

In other words, f == g is only true if f is g is also true. The latter is faster, so just use is.

Don't confuse this with methods; Python produces new method objects each time you access the object through attribute access (through the use of descriptors).

So:

class Foo:
    def bar(self): pass

f = Foo()
f.bar is f.bar

is always False because methods are created a-new on each attribute access. If you wanted to compare if they convey the same function you need to access the actual function object:

f.bar.__func__ is f.bar.__func__

is true.

Unlike functions, methods do implement an __eq__ equality method; see Why don't methods have reference equality?

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343