We use dunder methods when we’re overriding something that exists in python, something that python looks for
__init__
Reserved for special methods that have predefined behaviors and are part of python’s core functionality
just don’t use it
_name: 1 underscore
indicates a private property
self._secret
OFC, nothing is really “private” in Python, so it’s just a convention
__name : 2 underscores
self.__message
This is name mangling!
changing the names of class attributes that start with a double underscore __
change the attribute name to something that is less likely to conflict with subclasses
It makes the attribute unique to the specific class
class Person: def __init__(self): self.name = "Tony" self._secret = "hi" self.__msg = "I like turtles!"p = Person()print(p.name)print(p.__msg) ## DOESN'T PRINTprint(dir(p))# here, you sill see '_Person__msg' along with other methods# so you have to do like thisprint(p._Person_msg) # this prints "I like turtles!"
single underscore, class name, double underscore, and the attribute