The quickest way to get function name in Python code is the __name__ attribute. Every function object carries it as a plain string, so calculate_tax.__name__ returns 'calculate_tax':
print(calculate_tax.__name__) # calculate_tax
I ran every example below on Python 3.12.5 and took the screenshots in Command Prompt. Save each block as a .py file and run it with python file.py to follow along.
In this tutorial, we’ll read a function’s name with __name__ and __qualname__, find the name of the running function with inspect, and keep names intact inside decorators.
How do you get a function’s name with __name__?
__name__ holds the name from the def line. It doesn’t change when you assign the function to another variable, and it works for built-ins and lambdas too:
import functools
def calculate_tax(amount, rate=0.0825):
return round(amount * rate, 2)
tax = calculate_tax # an alias, same object
print(calculate_tax.__name__)
print(tax.__name__)
print(len.__name__, (lambda x: x).__name__)
texas_tax = functools.partial(calculate_tax, rate=0.0625)
print(getattr(texas_tax, "__name__", "no __name__"), "->", texas_tax.func.__name__)
Output:
calculate_tax
calculate_tax
len <lambda>
no __name__ -> calculate_tax

calculate_tax, a lambda reports <lambda>, and the partial has no name of its own.A functools.partial object has no __name__, so read .func.__name__ instead. Going the other way, from a string to a function, is covered in calling a function by its string name.
Get the full name of a method with __qualname__
For methods and nested functions, __name__ drops the context. __qualname__ (qualified name) adds the enclosing class or function, and __module__ tells you which file it came from:
class Invoice:
def total(self):
return 249.99
def report():
def helper():
pass
return helper
print(Invoice.total.__name__, "|", Invoice.total.__qualname__)
print(report().__qualname__)
print(f"{Invoice.total.__module__}.{Invoice.total.__qualname__}")
Output:
total | Invoice.total
report.<locals>.helper
__main__.Invoice.total
The nested function shows <locals> because it only exists inside report(). To list every name an object or module holds, use the dir() function in Python.
Get the name of a class or callable object
Classes have __name__ too, but an instance doesn’t. A safe pattern is getattr() with a fallback to the type’s name, which handles any object you’re passed:
class DiscountRule:
def __call__(self, total):
return round(total * 0.85, 2)
rule = DiscountRule()
items = [rule, print, str.upper, "not callable"]
for obj in items:
name = getattr(obj, "__name__", type(obj).__name__)
print(f"{name:<14} callable={callable(obj)}")
Output:
DiscountRule callable=True
print callable=True
upper callable=True
str callable=False
The DiscountRule instance has no name of its own, so the fallback prints its class name, while the string isn’t callable at all. You can check that first with the callable() function in Python.
Get the name of the current function with inspect
Inside a function you don’t have a variable that points to it. The inspect module reads the call stack instead: frame 0 is the running function and stack()[1] is its caller:
import inspect, sys
def ship_order(order_id):
me = inspect.currentframe().f_code.co_name
caller = inspect.stack()[1].function
print(f"{me}() called by {caller}() for order {order_id}")
print("sys._getframe:", sys._getframe().f_code.co_name)
def checkout():
ship_order(1042)
checkout()
Output:
ship_order() called by checkout() for order 1042
sys._getframe: ship_order

inspect.stack() builds every frame, so it’s slow in hot loops; currentframe() is the cheaper call. To see how the stack grows one frame per call, read recursion in Python.
Why does a decorator change the function name?
A decorator replaces your function with its inner wrapper, so the name changes too. functools.wraps copies __name__, __qualname__ and the docstring back onto the wrapper:
import functools
def log_calls(func):
@functools.wraps(func) # keeps func.__name__
def wrapper(*args, **kwargs):
print(f"Running {func.__name__}{args}")
return func(*args, **kwargs)
return wrapper
def plain(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@log_calls
def add_shipping(total):
return round(total + 7.99, 2)
@plain
def add_discount(total):
return round(total * 0.9, 2)
print(add_shipping(52.50))
print(add_shipping.__name__, "|", add_discount.__name__)
Output:
Running add_shipping(52.5,)
60.49
add_shipping | wrapper

functools.wraps keeps add_shipping; the plain one reports wrapper.Logging decorators like this are the most common place you’ll need a function’s name. Class-based decorators use update_wrapper(); see class decorators in Python.
If you’re working with functions, these guides fit well next:
- How to define a function in Python
- The __dict__ attribute of a Python class
- How to exit a function in Python
- Dynamic attributes with setattr() and getattr()
Frequently asked questions
How do I get a function name as a string in Python?
Read func.__name__. It’s already a string, so you don’t need str().
What is the difference between __name__ and __qualname__?
__name__ is the bare name; __qualname__ adds the class or enclosing function, like Invoice.total.
How do I get the name of the function that’s currently running?
Use inspect.currentframe().f_code.co_name inside it, or inspect.stack()[1].function for the caller.
Why does my decorated function report the name wrapper?
The decorator returned its inner function. Add @functools.wraps(func) above the wrapper to copy the original name.
Does a lambda have a function name?
Every lambda reports <lambda>, even after you assign it to a variable. Use def if the name matters.
Where are __qualname__ and frame objects documented?
See the inspect module in the Python docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn