Skip to content

Instantly share code, notes, and snippets.

@NegativeMjark
Last active August 29, 2015 14:10
Show Gist options
  • Save NegativeMjark/fda56adeabcdf54c89dc to your computer and use it in GitHub Desktop.
Save NegativeMjark/fda56adeabcdf54c89dc to your computer and use it in GitHub Desktop.
Notes on CPython

My Little Python

Everything in python is an object. All objects have a type. Most objects have an instance dictionary. Types can be constructed by calling type("name for type", (parents for type,), {instance dict for type}). Types have a method resolution order which is determined from their parents using http://en.wikipedia.org/wiki/C3_linearization. All operators in python can be overridden including the "." operator. So a.b is really finding a __getattribute__ in one of the types of a and calling it. However CPython needs an internal mechanism for finding the __getattribute__. This mechanism isn't exposed as a builtin but would look something like this in python code:

def get_override(object_instance, name):
    for mro_type in type(object_instance).mro():
        if name in mro_type.__dict__:
            return mro_type.__dict__[name]

The implementation of __getattribute__ on objects can be further customised by descriptors and through __getattr__. The object.__getattribute__ in CPython looks something like:

def object_get_attribute(object_instance, name):
    if name in object_instance.__dict__:
        return object_instance.__dict__[name]

    type_instance = type(object_instance)

    for mro_type in type_instance.mro():
        if name in mro_type.__dict__:
            entry = mro_type.__dict__[name]
            __get__ = get_override(entry, "__get__")
            if __get__:
                return __get__(entry, object_instance, type_instance)
            else:
                return entry

    __getattr__ = get_override(object_instance, "__getattr__")
    if __getattr__:
        return __getattr__(object_instance, name)
    else:
        raise AttributeError()

While the type.__getattribute__ in CPython looks something like:

def type_get_attribute(type_instance):

    for mro_type in type_instance.mro():
        if name in mro_type.__dict__:
            entry = mro_type.__dict__[name]
            __get__ = get_override(entry, "__get__")
            if __get__:
                return __get__(entry, None, type_instance)
            else:
                return entry

    metatype_instance = type(type_instance)

    for mro_metatype in metatype_instance.mro():
        if name in mro_metatype.__dict__:
            entry = mro_metatype.__dict__[name]
            __get__ = get_override(entry, "__get__")
            if __get__:
                return __get__(entry, type_instance, metatype_instance)
            else:
                return entry

    __getattr__ = get_override(type_instance, "__getattr__")
    if __getattr__:
        return __getattr__(type_instance, name)
    else:
        raise AttributeError()

Classes

Defining a class A:

class A(my_parent):
    __metaclass__ = my_meta_class
    my_class_variable = 42
    def my_method(self):
         pass

Is the same as:

def A():
    __metaclass__ = my_meta_class
    my_class_variable = 42
    def my_method(self):
         pass
    return locals()

A = my_meta_class("A", (my_parent,), A())

Decorators

Defining a decorated function:

@outer
@inner
def f():
    pass

Is the same as:

def f():
    pass
f = inner(f)
f = outer(f)

Operators

Operator Overrides
a.name a.__getattribute__("name"), a.name.__get__(a, type(a)), a.__getattr__("name")
a.name = b a.__setattr__("name", b), a.name.__set__(a, type(a), b)
del a.name a.__delattr__("name"), a.name.__del__(a, type(a))
if a: a.__nonzero__, a.__len__
i in a bool(a.__contains__(i))
a[i] a.__getitem__(i)
a[i:j:k] a.__getitem__(slice(i, j, k))
a[i] = b a.__setitem__(i, b)
del a[i] a.__delitem__(i)
a + b a.__add__(b), b.__radd__(a)
a(*b,**c) a.__call__(*b, **c)
with a as b: b = a.__enter__(), a.__exit__(*sys.exc_info())
for _ in a: b = a.__iter__(), b.__next__()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment