self.__class__ is a reference to the type of the current instance.
For instances of abstract1, that'd be the abstract1 class itself, which is what you don't want with an abstract class. Abstract classes are only meant to be subclassed, not to create instances directly:
>>> abstract1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NotImplementedError: Interfaces can't be instantiated
For an instance of a subclass of abstract1, self.__class__ would be a reference to the specific subclass:
>>> class Foo(abstract1): pass
...
>>> f = Foo()
>>> f.__class__
<class '__main__.Foo'>
>>> f.__class__ is Foo
True
Throwing an exception here is like using an assert statement elsewhere in your code, it protects you from making silly mistakes.
Note that the pythonic way to test for the type of an instance is to use the type() function instead, together with an identity test with the is operator:
class abstract1(object):
def __init__(self):
if type(self) is abstract1:
raise NotImplementedError("Interfaces can't be instantiated")
type() should be preferred over self.__class__ because the latter can be shadowed by a class attribute.
There is little point in using an equality test here as for custom classes, __eq__ is basically implemented as an identity test anyway.
Python also includes a standard library to define abstract base classes, called abc. It lets you mark methods and properties as abstract and will refuse to create instances of any subclass that has not yet re-defined those names.
self.__class__ is a reference to the type of the current instance.
For instances of abstract1, that'd be the abstract1 class itself, which is what you don't want with an abstract class. Abstract classes are only meant to be subclassed, not to create instances directly:
>>> abstract1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NotImplementedError: Interfaces can't be instantiated
For an instance of a subclass of abstract1, self.__class__ would be a reference to the specific subclass:
>>> class Foo(abstract1): pass
...
>>> f = Foo()
>>> f.__class__
<class '__main__.Foo'>
>>> f.__class__ is Foo
True
Throwing an exception here is like using an assert statement elsewhere in your code, it protects you from making silly mistakes.
Note that the pythonic way to test for the type of an instance is to use the type() function instead, together with an identity test with the is operator:
class abstract1(object):
def __init__(self):
if type(self) is abstract1:
raise NotImplementedError("Interfaces can't be instantiated")
type() should be preferred over self.__class__ because the latter can be shadowed by a class attribute.
There is little point in using an equality test here as for custom classes, __eq__ is basically implemented as an identity test anyway.
Python also includes a standard library to define abstract base classes, called abc. It lets you mark methods and properties as abstract and will refuse to create instances of any subclass that has not yet re-defined those names.
The code that you posted there is a no-op; self.__class__ == c1 is not part of a conditional so the boolean is evaluated but nothing is done with the result.
You could try to make an abstract base class that checks to see if self.__class__ is equal to the abstract class as opposed to a hypothetical child (via an if statement), in order to prevent the instantiation of the abstract base class itself due to developer mistake.
python - What is the purpose of the `self` parameter? Why is it needed? - Stack Overflow
Python class __init__ and self
Could someone explain the use of "self" when it comes to classes.
Can Someone explain to me what is self and init in python?
Videos
The reason you need to use self is because Python does not use special syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically but not received automatically, the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self.
Let's say you have a class ClassA which contains a method methodA defined as:
class ClassA:
def methodA(self, arg1, arg2):
... # do something
and objectA is an instance of this class.
Now when objectA.methodA(arg1, arg2) is called, python internally converts it for you as:
ClassA.methodA(objectA, arg1, arg2)
The self variable refers to the object itself.
Ik this is a basic question but I'm just learning to code and I'm learning about classes. For whatever reason I cannot understand or grasp the use of the self variable in fictions of classes. Hopefully someone's explanation here will help me...
I tried learning OOP from many video tutorials and documentation but I'm not understanding why we really need it or what is the use of it.
So it would be really helpful if someone could explain to me like a child what is the need for self and init in python.
Also, If you could tell me how did you fully grasp the concept of OOP in Python that would be really beneficial to me.
Thank You.
You have to add “self” as an argument to a class method. Why this specific syntax and how does it get interpreted? Is this because it inherits from the Python object model?
Is there any language where public methods do not contain “self” as an argument?
Thank you
Update
In Python 3.11 the module is named typing instead of typing_extensions
from typing import Self
class Node:
"""Binary tree node."""
def __init__(self, left: Self, right: Self):
self.left = left
self.right = right
This might be helpful:
from typing_extensions import Self
class Node:
"""Binary tree node."""
def __init__(self, left: Self, right: Self):
self.left = left
self.right = right
typing_extensions offers a Self class to reference class itself which I think is most elegent way to self-reference(PEP 673).
As others have mentioned, you can also use string literals. But it comes to problem when you have multiple type hints.
# python 3.10
var: str | int
And then you write something like
class Node:
def __init__(self, var: 'Node' | SomeClass):
self.var = var
It will raise a TypeError: unsupported operand type(s) for |: 'str' and 'type'.
While this, as other answers have pointed out, is not a problem due to the dynamic typing, in fact, for Python3, this is a very real issue when it comes to type annotations. And this will not work (note a type annotation of the method argument):
class A:
def do_something_with_other_instance_of_a(self, other: A):
print(type(other).__name__)
instance = A()
other_instance = A()
instance.do_something_with_other_instance_of_a(other_instance)
results in:
def do_something_with_other_instance_of_a(self, other: A):
NameError: name 'A' is not defined
more on the nature of a problem here: https://www.python.org/dev/peps/pep-0484/#the-problem-of-forward-declarations
You can use string literals to avoid forward references

Other way is NOT using python3-style type annotation in such cases,
and this is the only way if you have to keep your code compatible with earlier versions of Python.
Instead, for the sake of getting autocompletion in my IDE (PyCharm), you can docstrings like this:

Update: alternatively, instead of using docstrings, you can use "type: " annotations in a comment. This will also ensure that mypy static type checking will work (mypy doesn't seem to care about docstrings):
