Consider this code:
class Person(object):
def sayHello(self):
return 'Hello'
print(Person().sayHello is Person().sayHello)
I would expect it to show True. Why does it show False?
Consider this code:
class Person(object):
def sayHello(self):
return 'Hello'
print(Person().sayHello is Person().sayHello)
I would expect it to show True. Why does it show False?
I'm going to assume you are intentionally comparing the method objects themselves—and not that you really wanted to compare the output strings and just forgot to put
()
aftersayHello
.Try this experiment:
You'll see that
a.sayHello
displays as something like...whereas
b.sayHello
displays similarly but with a different parent instance pointer:The bound method of one instance of a
Person
is itself a different instance (of a method) from the bound method of the same name from a differentPerson
instance. You can confirm this withid(a.sayHello)
andid(b.sayHello)
which return the identity hashes of the two respective bound methods—they'll be different. Since your codePerson().sayHello is Person().sayHello
creates two differentPerson
instances on the fly, the situation is the same as with my named instance examplesa
andb
.It would be
True
if you calledsayHello
:In your code you're actually comparing the methods on the objects and checking whether they have the same identity (which they don't). Also note the difference between:
and
In the first, you're comparing the identity of the objects (which is the same due to the string being reused, call
id("Hello")
multiple times to see that). In the second, you're comparing the contents of the strings to see if they're equal (i.e., have the same characters). Now, the same strings would also have the same identity but I'm not sure whether that assumption holds across all Python implementations.The is operator means both variables point to the same object instead of having the same value. See Stack Overflow question Understanding Python's “is” operator.
If you want an expression which returns
True
you can try this:Just to add to the confusion, execute:
and even:
This is because:
say
refers toPerson.sayHello
which is a function, which can be called, but which needs a parameter, but in this particular case the parameter is irrelevant.Now, if you don't want to keep supplying the useless parameter, you can have one automatically bound:
They are two different instances of the same class. The
sayHello
functions are bound methods.That is, if you have a class instance:
and you lookup an attribute on it:
then Python first looks at the actual attributes of the instance, and if it does not find the attribute there, it looks at the class. If it finds a class method of that name, it turns it into a bound method, bound to this instance. That is the magic that results in the object instance being passed as the first argument (
self
) tosayHello
.So
Person().sayHello is Person().sayHello
creates two instances, creates two different bound methods based on the same method defined on the class, and thusis
returnsFalse
because they're different methods.Methods on are bound to instances at runtime. When you run the following code:
you create two instances and each time you have a different memory address.
Note: All we have in Python is runtime; there is no such thing as a separate compile time.