Как в Python узнать имя функции в которой выполняется код?

Как в Python узнать имя функции в которой выполняется код? Желательно не устанавливая дополнительные модули.

Например 1:

class Test:
    def func_1():
        print(f'Print from {name_this_function}')

    def func_2():
        print(f'Print from {name_this_function}')

    def func_3():
        print(f'Print from {name_this_function}')

test = Test()
test.func_1()
test.func_2()
test.func_3()

Пример 2:

class Test:
    def func_1():
        self.where_are_you()

    def func_2():
        self.where_are_you()

    def func_3():
        self.where_are_you()

    def where_are_you():
        if current_func == 'func_1':
            print('Print from func_1')
        elif current_func == 'func_2':
            print('Print from func_2')
        elif current_func == 'func_2':
            print('Print from func_2')

test = Test()
test.func_1()
test.func_2()
test.func_3()

При выполнении кода хочу видеть такой вывод:

Print from func_1
Print from func_2
Print from func_3


Ответы (5 шт):

Автор решения: Xander
import traceback


def say_my_name():
    stack = traceback.extract_stack()
    print('Print from {}'.format(stack[-2][2]))


class Test:

    def func_1(self):
        say_my_name()

    def func_2(self):
        say_my_name()

    def func_3(self):
        say_my_name()


test = Test()
test.func_1()
test.func_2()
test.func_3()

Но вообще согласен с Wairua - лучше явно передавать параметр с указанием нужной стратегии.

→ Ссылка
Автор решения: Дмитрий

Как вариант:

import sys

class Test:
    def func(self):
        print(f'Print from {sys._getframe().f_code.co_name}')

test = Test()
print(test.func())
→ Ссылка
Автор решения: Егор

Если вы задаете функцию в качестве аргумента, внутри другой функции или где либо еще вызываете, имя функции можно узнать так:

func.__name__

В вашем примере будет:

print(f'Print from {func_1.__name__}')

→ Ссылка
Автор решения: Ferrus
def print_function_name(decorated_function):
    def wrapper_function(*args, **kwargs):
        print('Print from {0}'.format(decorated_function.__name__))
        return decorated_function(*args, **kwargs)

    return wrapper_function


class Test:
    @print_function_name
    def func_1(self):
        ...

    @print_function_name
    def func_2(self):
        ...

    @print_function_name
    def func_3(self):
        ...


test = Test()
test.func_1()
test.func_2()
test.func_3()
→ Ссылка
Автор решения: Perchik
def name_func(func_in):

    name_f = func_in.__name__
    print(name_f)
    return func_in()

@name_func

def func_1():
    
    for i in range(3):
        print(i)
→ Ссылка