4

I would like to know which is the order of all the actions made by the interpreter behind the scenes (no matter if they are explicitly declared or not).

For example:

  • __init__ call
  • super() call
  • __new__ call
  • global variables
  • initialization of constructor variables
  • decorators calls etc.

EDIT: let's assume it's a class which has it all (you name it)

global_var = 2468
class A(superA):
    class_var = 1234

    __init__(self):
        superA.__init__(self)
        another_var = 5678

    @random_decorator
    def method(self):
        # do stuff
Alex
  • 681
  • 2
  • 9
  • 18
  • 1
    Most of the stuff you list is 100% dependent on your actual code. `__new__` and `__init__` are called; either of these may or may not have `super` calls, variables, decorators, etc. – Wooble Oct 11 '12 at 13:57
  • 1
    It seems like a question like this is usually born out of a desire to understand something in your *code* which isn't behaving the way you want it to ... If that's the case, you could provide a few more details about what you're seeing and what you expect (an actual code example would be great to illustrate the problem too) that could help to understand what you're having trouble with. – mgilson Oct 11 '12 at 14:04
  • @mgilson It's true, it comes from this question I asked before: http://stackoverflow.com/questions/12838114/how-to-initialize-global-variable-at-each-class-invocation in the end it turned out to be a timing problem and that I did not know how the order of class initializations – Alex Oct 11 '12 at 14:07
  • the decorator thing does make sense actually. think of it this way: the decorators are called as a part of putting the class itself, together. then once the class is put together, calling it calls its methods. – Claudiu Oct 11 '12 at 15:34
  • Never edit your answer into your question. Please post it as a separate answer, but only if it provides additional info over the other answers. Then accept the best one (which might be yours). – Maarten Bodewes Oct 11 '12 at 23:58

2 Answers2

4
class Foo(object):
    def __init__(self, *args, **kwargs):
        pass

>>> foo = Foo(a, b=c)
  1. It's call type.__call__(Foo, a, b=c)... (instead type can be metaclass of your class)
  2. ...which call Foo.__new__(a, b=c) which create instance of Foo...
  3. ...and call foo.__init__(a, b=c) and return foo.

In other word, b = B(*args) works like type.__call__(B, *args) where type.__call__ can be expressed as:

class type(object):

    def __call__(cls, *args, **kwargs)
         obj = cls.__new__(*args, **kwargs)
         obj.__init__(*args, **kwargs)
         return obj

Function super is executed just in the place where you call it (like a normal function).

Decoration is performed in the initialization of classes and methods, replacing them on the wrappers.

Full example:

def dec(func):
    print 'decorate', func.__name__
    def wrapper(*args):
        print 'call wrapper of', func.__name__
        return func(*args)
    return wrapper

class A(object):

    def __new__(*args):
        print 'call A.__new__'
        return object.__new__(*args)

    def __init__(self, *args):
        print 'call A.__init__'


class MyMetaclass(type):

    def __call__(mcls, *args):
        print 'call MyMetaclass.__call__'
        return super(MyMetaclass, mcls).__call__(*args)

class B(A):

    __metaclass__ = MyMetaclass

    @dec
    def __new__(*args):
        print 'call B.__new__'
        return A.__new__(*args)

    @dec
    def __init__(self, *args):
        print 'call B.__init__'
        return super(B, self).__init__(*args)

print 'start creating instance'
b = B()
print 'end creating instance'

Result:

decorate __new__
decorate __init__
start creating instance
call MyMetaclass.__call__
call wrapper of __new__
call B.__new__
call A.__new__
call wrapper of __init__
call B.__init__
call A.__init__
end creating instance
defuz
  • 26,721
  • 10
  • 38
  • 60
2

It's all rather straightforward. When a module is loaded, code is run from the top to the bottom. Global variables will thus be instantiated as they appear in the module code. When a function is called, the code in it runs from top to bottom.

Decorators are somewhat of an exception in that they are called after the function they are decorating has been defined, in bottom to top order. So if you have:

@hits
@dies
@rofls
def watcher(): pass

it's the same as:

def watcher(): pass
watcher = hits(dies(rofls(watcher)))

This makes sense if you think of each decorator wrapping everything below it.

When an object is created, first __new__ is called, then __init__. super() is called if you happen to have a call to it somewhere, much like anything else... 'constructor variables' are just initialized whenever you happen to have variable assignment in an __init__.

EDIT: To look at your example:

class A(superA):
    class_var = 1234

    def __init__(self):
        superA.__init__(self)
        another_var = 5678

    @random_decorator
    def method(self):
        # do stuff

I will instead teach you how to fish.

def random_decorator(f):
    print "random_decorator called"
    return f

def init_var(varname, val):
    print '%s being initialized' % (varname,)
    return val

class superA(object):
    def __new__(cls):
        print 'superA.__new__ called'
        return super(superA, cls).__new__(cls)
    def __init__(self): 
        print "superA.__init__ called"

class A(superA):
    class_var = init_var('class_var', 1234)

    def __new__(cls):
        print 'A.__new__ called'
        return super(A, cls).__new__(cls)

    def __init__(self):
        print 'A.__init__ called'
        superA.__init__(self)
        another_var = init_var('another_var', 5678)

    @random_decorator
    def method(self):
        print 'method called'
        # do stuff

    class_var2 = init_var('class_var2', 9012)

A().method()

See what order the print statements come out in.

Claudiu
  • 224,032
  • 165
  • 485
  • 680