Trailing underscores are used to avoid name collisions, especially with builtin names. Suppose I make my own filter
function, I may define it with a trailing underscore to prevent collission with the builtin filter
def filter_(some_iterable):
# my filter function
Double leading underscores in class method names (e.g. __my_method
invoke Python's Name Mangling.
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)
__dunder__
names are typically reserved for "magic methods" -- but there's not really a whole lot of 'magic' behind it. For example, you may define a __repr__
to give your class a nice repr, without it your class repr will look something like <__main__.Foo object at 0x000001F5D1551978>
but if you define __repr__
class Foo(object):
#whatever
def __repr__(self):
return '<Foo object>'
There are a bunch of these methods that affect the interaction of a class with many methods like len
, hash
, operators like +
, etc.