It seems like you have a more fundamental thing to understand in Python:
- All code is execute top to bottom
- Even on the compiled byte code file, there are no Classes, or functions present
- Classes and functions are created in Python in the order they are found in the code,
as each file is imported.
Once you understand that, and that decorators are just the equivalent of
replacing a declared function with the return value of the decorator, i.e.:
@deco
def myfunc():
pass
# is equivalent to:
def myfunc():
pass
myfunc = deco(myfunc)
You start to understand what is going on.
SO, when Python compiler finds a block in source code like:
def a():
pass
It records in bytecode the code object for the function body (the pass
statement),
and the bytecode to create a function object from this code, and the elements contained in the def statement (essentially a call to types.FunctionType). On running the code (after the compile pass), the returned object of this call is then bound to the name a
in the namespace where the function was found. Only at this point the "function object" is existing, and can be called.
If there are decorators preceding the def
statement, they are called in bottom-to-top
order, before the name is actually bound - the function name is just bound to the returned object of the last decorator.
A different thing goes for class bodies:
- When finding a class block, the interpreter creates a new namespace
- it enters the class body and starts executing the lines there, in order (it does not execute the body of functions, just compile then to bytecode)
- So one could even put
for
or while
loops directly inside class bodies - those loops would run at class creation time (usually when the module is imported).
- And - methods inside the class body are created as functions as the class is executed, as described above
- when the class body is over, Python calls the built-in
type
factory to actually create the class: the parameters are the class name, class bases, and the names of objects
(functions and attributes alike) found inside the class body as a dictionary.
- The returned object of this call to
type
(or rather, to the class' metaclass) is bound to the class name in the namespace where the "class" statement is.
- If there are class decorators, they are called with the class object returned, before the name binding step,as it happens with functions.
(this is actually simpler than creating functions, and you
can actually find a lot more code in the wild which does create a new class without
a class body, calling type
instead, than code that creates new functions calling FunctionType)
So - answering your question: yes - "decorators are called in the order they are encountered" - but that is natural once you find out how Python works.
So, if the above explanation is a bit vague, check what this does:
def log(func):
print(func.__name__)
return func
class A(object):
for i in range(5):
@log
def func(self):
pass
locals()["func_%d" % i] = func
And compare it with:
class B(object):
for i in range(5):
def func(self):
pass
func.__name__ = "func_%d" % i
locals()["func_%d" % i] = log(func)