Логика предельно простая - на момент обращения к элементу он должен быть определён.
Простой пример:
def func_B(s):
print('B says:')
func_A(s)
def func_A(s):
print('Hello from A to', s)
func_B('the world')
Данный код отработает. Почему, ведь func_A() описана после её вызова в func_B()?
Потому что поиск этой функции произойдёт в момент
вызова func_B() - а тогда функция func_A() уже будет определена.
А вот тут поменять местами не получится:
DEFAULT = 'world'
def func_C(s = DEFAULT):
print('Hello,', s)
Потому что обращение к DEFAULT происходит в момент определения func_C(), а не в момент её выполнения.