Confused about double leading and trailing underscore use?

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.

/r/learnpython Thread