"everything is object in Python", so "everything" (maybe not exactly everything, I don't know) is a class instance and has potentially attributes and methods.
That said you have to know that, by convention, every method whom name begins with __
is considered as private (and is almost really protected) and you should not use it directly.
Every method whom name starts and ends by __
is called a magic method and has a pretty well defined role. They could be considered as a sort of hooks bound to particular operators or moments in the object lifecycle.
For example __add__
is the method bound to the +
operator. When you do an addition, you are actually calling the __add__
method of a number, giving it another number as parameter.
As you noticed, you also can call directly the __add__
method if you want, but it is not encouraged.
Python is a high-level interpreted language. It provides many facilities and a clear syntax that allows to concentrate on real problems rather than implementation details.
Those facilities do not come from nowhere and are a benefit provided by (among others) an internal data model.
This data model is certainly not as lightweight as a custom handcrafted C data structure specialy designed for a single problem but it is pratical and usable in many situations (and still reasonably lightweight and well performing for many usages).
If you are concerned by memory optimisation and extreme-performance, You probably should look some lower level languages like C
or Go
.
But keep in mind that solving any problem could then probably take much more time :)