Master Python Decorators: Add Powerful Features Without Changing Code
This article explains what Python decorators are, why they are useful for extending functions without modifying original code, and provides step‑by‑step examples—including simple, parameterized, and custom decorators—along with practical usage patterns and tips for preserving function metadata.
1. Simple definition of decorators
Outer function returns a reference to an inner function; the inner function can access variables from the outer scope.
2. Purpose of decorators
Decorators let you add new functionality to a function without changing its existing code.
def run():
print('我会跑')
fun()Now we want to add a "I can sing" feature using a decorator.
3. Example understanding
(1) Decorator without parameters
def outer(fun):
def inner():
fun() # fun is the outer function variable, used inside inner
return inner # inner is the reference to the inner function(2) Decorator with parameters
def func(fun):
def add(*args, **kwargs):
return fun(*args, **kwargs)
return addUsing the pattern above we can implement the "I can sing" functionality.
def outer(fun):
def inner(*args, **kwarge):
print("我会唱歌")
return fun(*args, **kwarge)
return inner4. How to use decorators
# Method 1: Use @decorator_name above the function
@outer
def run():
print('我会跑')
run()
# Method 2: Assign manually
def run():
print('我会跑')
run = outer(run) # equivalent to @outer
run()
# Output:
我会唱歌
我会跑To inspect the original function name inside a decorator, you can print fun.__name__. Without preserving metadata, the decorated function's __name__ becomes inner. Use functools.wraps to keep the original name.
from functools import wraps
def outer(fun):
@wraps(fun)
def inner(*args, **kwargs):
print(fun.__name__, 11111111111)
print("我会唱歌")
return fun(*args, **kwargs)
return inner
@outer
def run():
print('我会跑')
print(run.__name__, 6666666) # outputs: run 66666665. Custom decorator example
def subuser_keymanage(view_func):
'''Implements user permission check'''
def _wrapper_view(request, *args, **kwargs):
user = request.user
customer = user.customer.customer_id
select_status = get_curuser_permission(user=user, customer=customer)
if not select_status:
return render_response(request, ErrorCode.FAILED)
return view_func(request, *args, **kwargs)
return _wrapper_view
@subuser_keymanage
def generate_subuser_ak_sk(request):
params = json.loads(request.body)
user_id_only = params.get("user_id")
# ... omitted core logic ...
return render_response(request, ErrorCode.FAILED)6. Summary of decorators
Decorators greatly reduce code duplication and are important for clean code standards. Even without deep understanding, following the fixed pattern lets you create sophisticated decorators quickly.
Logging decorator example
import logging
def use_logging(level):
def decorator(func):
def wrapper(*args, **kwargs):
if level == "warn":
logging.warn("%s is running" % func.__name__)
elif level == "info":
logging.info("%s is running" % func.__name__)
return func(*args)
return wrapper
return decorator
@use_logging(level="warn")
def foo(name='foo'):
print("i am %s" % name)
foo()
# Output:
# i am foo
# WARNING:root:foo is runningSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
