>>> class Test(object): pass
>>> t = Test()
>>> type(t) is t.__class__
True
>>> type(t)
__main__.Test
So those two are the same. I would use self.__class__ since it's more obvious what it is.
However, type(t) won't work for old-style classes since the type of an instance of an old-style class is instance while the type of a new-style class instance is its class:
>>> class Test(): pass
>>> t = Test()
>>> type(t) is t.__class__
False
>>> type(t)
instance
Answer from ThiefMaster on Stack OverflowPython: self.__class__ vs. type(self) - Stack Overflow
Using `Self` with classmethod and a `Self` class attribute - Typing - Discussions on Python.org
PEP 673 -- Self Type
The Self type in Python 3.11
>>> class Test(object): pass
>>> t = Test()
>>> type(t) is t.__class__
True
>>> type(t)
__main__.Test
So those two are the same. I would use self.__class__ since it's more obvious what it is.
However, type(t) won't work for old-style classes since the type of an instance of an old-style class is instance while the type of a new-style class instance is its class:
>>> class Test(): pass
>>> t = Test()
>>> type(t) is t.__class__
False
>>> type(t)
instance
As far as I am aware, the latter is just a nicer way of doing the former.
It's actually not that unusual in Python, consider repr(x), which just calls x.__repr__() or len(x), which just calls x.__len__(). Python prefers to use built-ins for common functions that you are likely to use over a range of classes, and generally implements these by calling __x__() methods.
So, this was one of the new features added in Python 3.11.
I understand that it's whole purpose is to avoid typing class name as a string (e.g. "Shape"), but use Self type directly (which is a local alias to Shape).
I understand it is mainly useful in the following scenarios:
I. Implementing fluent interfaces (when each method returns the object itself, so multiple method calls could be chained):
class Shape:
def set_size(self, size: float) -> Self:
self.size = size * 100.0 # normalize
return selfII. Implementing factory methods:
class Shape:
@staticmethod # or @classmethod
def load_from_disk(filename: string) -> Self:
obj = decrypt_and_deserialize(filename)
return objBut are there any other useful use cases?
Shall I annotate each self parameter of each class method with Self?
Shall __new__() method be returning Self?