Why do some functions have underscores __ before and after the function name?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python, names like __init__, __str__, and __len__ are special methods, often called dunder methods because they have double underscores before and after the name. They are not ordinary naming style choices. They are hooks into Python's object model that let your objects participate in built-in language behavior.
Why The Double Underscores Exist
Python needs a set of reserved method names with well-defined meaning. The double-underscore convention marks those names as interpreter-recognized protocol methods rather than normal application methods.
For example:
- '
__init__controls instance initialization' - '
__str__controls user-facing string conversion' - '
__repr__controls developer-oriented representation' - '
__len__controls behavior oflen(obj)' - '
__getitem__controls indexing such asobj[0]'
These names are special because Python itself looks for them when certain syntax or built-in functions are used.
Example: Object Initialization
A simple class with __init__ looks like this:
When you write User("Ada"), Python creates an instance and then calls __init__ automatically. You do not call it directly in ordinary code.
Example: String Representation
Special methods also control how objects appear when printed.
This is why dunder methods matter. They let your class integrate naturally with the rest of the language.
Example: Operator Overloading
Python also uses special methods for operators.
The expression v1 + v2 works because Python translates it into a call that consults __add__.
These Are Protocol Methods, Not Just "Magic"
Calling them magic methods can make them sound mysterious, but they are better understood as protocol methods.
If your object implements the right methods, it can behave like:
- a container
- an iterable
- a numeric value
- a context manager
- a callable object
For example, implementing __iter__ and __next__ lets an object work in a for loop. Implementing __enter__ and __exit__ lets it work in a with statement.
What About Leading Double Underscores Only
Do not confuse dunder methods with names like __hidden.
A name with leading double underscores but not trailing double underscores triggers name mangling inside classes. That is a different feature.
So these are different:
- '
__init__is a special method name recognized by Python' - '
__valueis a name-mangled attribute, not a protocol method'
That distinction matters a lot for readability and correctness.
Should You Invent Your Own Dunder Names
No. You should not create arbitrary names like __myfeature__. Names of the form __name__ are conventionally reserved for Python's own protocols and special behavior.
If you need a normal helper method, give it a normal method name.
Common Pitfalls
A common mistake is assuming dunder methods are automatically called in all circumstances. For example, defining __str__ does not change repr(obj), and defining __len__ does not make the object iterable.
Another issue is confusing dunder methods with private naming. Double leading underscores without trailing underscores are about name mangling, not interpreter protocols.
Developers also sometimes call special methods directly in ordinary code even when the built-in syntax is clearer. Writing len(obj) is better than obj.__len__() unless you are debugging something specific.
Finally, do not invent your own dunder method names. Stick to the ones Python actually defines.
Summary
- Names like
__init__and__str__are special Python protocol methods. - They let your objects work naturally with built-in syntax and functions.
- The double underscores mark reserved interpreter-recognized names.
- Do not confuse dunder methods with name-mangled attributes such as
__value. - Use the built-in language features that trigger these methods instead of calling them manually in normal code.

