• __new__() and __init__()

__new__() is always called before __init__().
Use __new__ when you need to control the creation of a new instance.
Use __init__ when you need to control initialization of a new instance.

__new__ is the first step of instance creation. It’s called first,
and is responsible for returning a new instance of your class. In
contrast, __init__ doesn’t return anything; it’s only responsible for
initializing the instance after it’s been created.

In general, you shouldn’t need to override __new__ unless you’re
subclassing an immutable type like str, int, unicode or tuple.

link

  • __getattr__() and __getattribute__()

We usually use obj.attributee or getattr(obj, field_name) to get the attribute value of an object.

When a attribute doesn’t exist for a object, it will call __getattr__(), while __getattribute__ is called whenever an attribute access occurs.
if __getattribute__ fails, __getattr__ is called.

If you need to catch every attribute regardless whether it exists or not, use __getattribute__ instead. The difference is that __getattr__ only gets called for attributes that don’t actually exist. If you set an attribute directly, referencing that attribute will retrieve it without calling __getattr__.

link

Example: when you wanna implement some logics like when the value of field1 is None, take the value of field2 of the object.