Функция в питоне - это объект первого рода.
В питоне всё - объекты. И функция и число и строка и список и словарь и класс и экземпляр класса.
У каждого объекта может быть много имён. Рассматривайте имя объекта, как ярлычок, привязанный к чайному пакетику.
print_friends_count(count)
Здесь print_friends_count это имя переменной, а скобочки после него заставляют вызывать объект, доступный пр этому имени как функцию. Вызов происходит с передачей единственного аргумента, который доступен по имени count.
Если в коде на питоне в каком-то выражении (а вызов функции - это выражение; результат вызова - это всегда какое-то значение, например None; да, None - это тоже объект, его возвращает функция по умолчанию) встречается какое-то имя, то это имя ищется в локальной области видимости этой функции (то есть в самой функции), потом в той области видимости, где объявлена функция, потом еще выше и так далее до самого модуля. Самая верхняя - глобальная область видимости - это модуль. Если имя не нашлось нигде, даже в модуле, то оно поищется среди __builtins__ - это такой словарик с именами и объектами, доступными везде. Если не найдётся и там, то будет ошибка.
В вашем случае функцию следовало оставить на уровне модуля. Вызвать ее можно будет где угодно внутри модуля, но при условии, что оператор объявления функции уже выполнен.
При запуске программы (или импорте модуля) по очереди выполняются все операторы (импорты, объявления функций/классов, присвоение имен результатам каких-то выражений...)
Мне кажется вам стоит скачать книжку Лутца про изучение питона с нуля и вдумчиво прочитать. По порядку.