To support the zero-argument form of super()
, the compiler adds an implicit reference to the class if __class__
or super()
are being used in a class method. See Creating the class object.
The example code you found (ab)uses this little factoid to create new instances of Position
when adding.
Personally, I'd use type(self)
instead, as that is the proper API method of determining the type or class of any object. type(self)
will use self.__class__
where appropriate:
def __add__(self, other):
return type(self)(self.x + other.x, self.y + other.y)
That is a good idea if you want to support subclassing. Any subclasses of Position
will return the correct subclassed type when being added together. Using __class__
does not do that, as it will always be pointing to Position
, even for subclasses:
>>> class Foo:
... def method(self):
... print(__class__)
... print(type(self))
...
>>> class Bar(Foo):
... pass
...
>>> Bar().method()
<class '__main__.Foo'>
<class '__main__.Bar'>
Of course, if that was your intention all along (to bypass subclasses), I'd still prefer using the explict class name over using __class__
; explicit is better than implicit.