Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python Decorators from Syntactic Sugar to Produ...

Python Decorators from Syntactic Sugar to Production-Grade Design Tool

Python decorators are among Python's most powerful and elegant features. Although their syntax is relatively simple, their capabilities extend far beyond adding an @ symbol before a function or class definition.

In this talk, delivered at Python Summit 2026, I explore how Python decorators work, how to build your own decorators, and how to use them effectively in production-grade software.

We begin with the fundamentals, examining Python's support for first-class functions and understanding what actually happens behind the scenes when a decorator is applied. From there, we move on to more advanced techniques, including function-based decorators, class-based decorators, nested decorators, and decorators that accept arguments.

The presentation includes practical code examples showing how decorators separate responsibilities, reduce code duplication, and improve software maintainability.

We also explore real-world applications of decorators, including:

Execution Time Measurement: Measuring function performance without modifying the original implementation.

Logging: Tracking function calls, arguments, and return values.

Caching: Improving performance by avoiding unnecessary repeated computations.

RESTful Web Services: Understanding how FastAPI uses decorators to define API endpoints.

Command-Line Applications: Exploring how Typer uses decorators to simplify CLI development.

An important part of the talk focuses on best practices for developing reliable, reusable, and maintainable decorators. We discuss preserving function metadata with functools.wraps, supporting arbitrary function arguments using *args and **kwargs, following the Single Responsibility Principle (SRP), proper exception handling, documentation, unit testing, and type hinting.

As AI increasingly generates software, understanding good software design becomes even more important. AI can produce code quickly, but evaluating its quality, maintainability, and correctness remains essential. Understanding decorators and the design principles behind them helps developers make better architectural decisions and work more effectively with AI-generated code.

Whether you are already familiar with Python decorators or want to better understand their capabilities, these slides offer practical examples, implementation techniques, and design principles to help you write cleaner, more maintainable Python code.

Code samples from the talk:
https://tinyurl.com/pythonsummitdecorators

More articles, courses, and software development resources:
https://lifemichael.com

Connect with me on LinkedIn:
https://linkedin.com/in/lifemichael

Thank you to the organizers of Python Summit 2026 and everyone who attended my session! 🐍🇵🇱

Avatar for life michael

life michael

October 19, 2026

More Decks by life michael

Other Decks in Technology

Transcript

  1. My name is Haim Michael. I live in Tel Aviv,

    and I am the CEO & founder of Zindell Technologies, Ltd. I have been into programming since my childhood. I have extensive experience with Java (30+ yrs), JavaScript (30+ yrs), C++ (30+ yrs), C# (20+ yrs), TypeScript (12+ yrs), Python (15+ yrs), PHP (20+ yrs), Scala (16+ yrs), and Kotlin (12+ yrs). blog.lifemichael.com Tel-Aviv, Israel
  2. My passion lies in teaching and lifelong learning. I continuously

    learn and evolve. Learning takes place in various forms. Learning is not limited to the formal educational systems. You thrive when you explore topics that genuinely interest you. blog.lifemichael.com Passion for Self Learning
  3. B.Sc. in Economics & Accounting Tel-Aviv University MBA (Information Systems

    Management) Teaching advanced topics in software development at leading academic institutions. Teaching Today Holon Institute of Technology Bar Ilan University Ben Gurion University Reichman University Tel-Aviv University Technion Institute of Technology blog.lifemichael.com My Academic Background
  4. Functional Programming (Scala) Classic Design Patterns FED Concurrent Programming (Threads

    in Java & Coroutines in Kotlin) Asynchronous Server-Side Development (Node.js & MongoDB) Cyber Security in the AI Era AI Agents Orchestration Design Patterns Micro Services Design Patterns Events Driven Architecture Spec-Driven Development with AI blog.lifemichael.com Academia
  5. Jacado - More Than 200 Games for Mobile Telephones –

    Years 2001- 2008 Zindell - Building AI Aligned Companies – Years 2026 - … nana.events prompo.ai zindrex.com ngager.pro jacado.games blog.lifemichael.com Passion to Build
  6. XtremeJ XtremePython xtremej.dev xtremepython.dev meetup.com/lifemichael XtremeJS XtremeAI xtremejs.dev xtremeai.dev More

    Than 4600 Members Online Community Conferences, since 2021 blog.lifemichael.com Conferences & Meetups
  7. Python Developers JavaScript Developers Professional Group on Facebook More than

    131000 Members facebook.com/groups/lifemichaelpython Professional Group on Facebook More than 35000 Members https://www.facebook.com/groups/407961892610345 More Than 2800 Professional Video Clips youtube.com/lifemichael More Than 18000 Followers https://linkedin.com/in/lifemichael blog.lifemichael.com Communities Builder
  8. Functions is an Object def total(a:int, b:int) -> int: return

    a + b f = total print(f(1,2)) total 12FC f 12FC 12FC function_is_object.py
  9. Introduction Decorators in Python allow us to add functionality to

    a function or a class we define. Similar to Attributes in C#, Annotations in Java/Scala/Kotlin, and Decorators in TypeScript.
  10. Developing Utilities with Typer import typer app = typer.Typer() @app.command()

    def hello(name:str, num:int) -> None: i = num while i > 0: print(f"Hello {name}") i -= 1 @app.command() def goodbye(name:str, num:int) -> None: i = num while i > 0: print(f"Goodbye {name}") i -= 1 if __name__ == "__main__": app() Check out Typer at https://typer.tiangolo.com
  11. Introduction When decorating a function (e.g. foo()), the decorator is

    invoked. The reference for foo is passed over. @decorator def foo(): pass is indirectly changed into foo = decorator(foo)
  12. Jump Start def uppercase(func): print("inside uppercase") def inner(): print("inside inner")

    data = func() return data.upper() return inner print("we love coding!") @uppercase def getGreeting(): print("inside getGreeting") return "good morning" #getGreeting = uppercase(getGreeting) print("we love python!") print(getGreeting()) jump_start.py The Output
  13. Jump Start F202 def uppercase(func): print("inside uppercase") def inner(): print("inside

    inner") data = func() return data.upper() return inner (1) uppercase A808 (4) inner A808 getGreeting A808 B212 print("we love coding!") @uppercase def getGreeting(): print("inside getGreeting") return "good morning" F202 function function data.upper() (5) func #getGreeting = uppercase(getGreeting) print("we love python!") (2) B212 function Return “good morning” print(getGreeting()) jump_start.py B212 (3)
  14. Decorating Function with Parameters In order to decorate the function

    foo that has parameter(s), we just need to make sure the signature of the function returned by the decorator allows delegating the call to foo.
  15. Decorating Function with Parameters def uppercase(func): print("inside uppercase") def inner(*args,

    **kwargs): print("inside inner") result = func(*args, **kwargs) return result.upper() if isinstance(result, str) else result return inner print("we love coding!") @uppercase def get_greeting(name: str, punctuation: str = "!"): print("inside get_greeting") return f"good morning, {name}{punctuation}" print("we love python!") #get_greeting = uppercase(get_greeting) print(get_greeting("Alice", punctuation="!!")) decorating_functions_with_parameters_kwargs The Output
  16. Using a Class as Decorator The decorator should be a

    callable object. It can be a function. I can also be a class we define together with the __init__ and the __call__ functions.
  17. Using a Class as Decorator class uppercase: def __init__(self, f):

    print("inside __init__") self.f = f def __call__(self, nickname): print("inside __call__") return self.f(nickname).upper() print("we love coding!") @uppercase def greet(nickname): return "Good Morning " + nickname #greet = uppercase(greet) print("we love python!") The Output print(greet("Danny")) class_as_decorator.py
  18. Using a Class as Decorator Might Be a Better Version

    class uppercase: def __init__(self, f): print("inside __init__") self.f = f def __call__(self, *args, **kwargs): print("inside __call__") return self.f(*args, **kwargs).upper() print("we love coding!") @uppercase def greet(nickname): return "Good Morning " + nickname #printing with kwargs print("we love python!") print(greet(nickname="Danny")) class_as_decorator_kwargs.py The Output
  19. Decorators Nesting We can place together more than one decorator.

    Doing so, we should imagine the decorators execution one after the other in the order in which they are listed (top to bottom). The output of each decorator execution is the input for the decorator above.
  20. Decorators Nesting def stars(func): print("inside stars") def inner(text): print("inside inner

    of stars") input = func(text) return "*** " + input + " ***" return inner def uppercase(func): print("inside uppercase") def inner(nickname): print("inside inner of uppercase") data = func(nickname) return data.upper() return inner @stars @uppercase def getGreeting(nickname): return "good morning " + nickname #getGreeting = stars(uppercase(getGreeting)) print(getGreeting("dave")) The Output decorators_nesting.py
  21. Decorators Nesting def stars(func): print("inside stars") def inner(*args, **kwargs): print("inside

    inner of stars") output = func(*args, **kwargs) return f"*** {output} ***" if isinstance(output, str) else output return inner Might Be a Better Version def uppercase(func): print("inside uppercase") def inner(*args, **kwargs): print("inside inner of uppercase") result = func(*args, **kwargs) return result.upper() if isinstance(result, str) else result return inner @stars @uppercase def greet(name, punctuation="!"): return f"Good Morning {name}{punctuation}" print(greet("Danny", punctuation="!!")) decorators_nesting_kwargs.py The Output
  22. Class Decorators We can develop decorators for classes. The object

    that represents a class is also a factory function we can decorate. def bang(func): def inner(): print("bang!!!") ob = func() return ob return inner @bang class Rectangle(): pass ob1 = Rectangle() ob2 = Rectangle() The Output class_decorators.py
  23. Class Decorators We can develop decorators for classes. The object

    that represents a class is also a factory function we can decorate. def bang(func): def inner(*args, **kwargs): print("bang!!!") ob = func(*args, **kwargs) return ob return inner Might Be a Better Version @bang class Rectangle(): pass ob1 = Rectangle() ob2 = Rectangle() The Output class_decorators_kwargs.py
  24. Decorators with Arguments We can develop a decorator that takes

    arguments when called. def bang(text): def f(func): def inner(): print(text) ob = func() return ob return inner return f Decorator Factory @bang(text="Picaso") class Rectangle(): pass The Output ob1 = Rectangle() ob2 = Rectangle() decorator_with_arguments.py
  25. Decorators with Arguments def bang(text, repeat=1): def f(func): def inner(*args,

    **kwargs): print((" " + text) * repeat if repeat > 1 else text) return func(*args, **kwargs) return inner return f @bang(text="Constructing Rectangle") class Rectangle: def __init__(self, width, height=1, **kwargs): self.width = width self.height = height self.extra = kwargs def area(self): return self.width * self.height rect = Rectangle(3, height=4, color="red") print(rect.area()) print(rect.extra.get("color")) Might Be a Better Version The Output decorator_with_arguments_kwargs.py
  26. Measuring Execution Time We can easily develop a decorator to

    measure the execution time of specific functions. import time def stopper(func): def inner(*args, **kwargs): start = time.perf_counter() value = func(*args,**kwargs) end = time.perf_counter() run = end - start print("running_time=",run) return value return inner
  27. Measuring Execution Time @stopper def doSomething(*args, **kwargs): total = 0

    for i in range(kwargs["times"]): total += i return total doSomething(times=99999) The Output
  28. Logging We can easily develop a decorator that will track

    each and every execution of a specific function. def tinylog(func): def f(*args, **kwargs): args1 = [repr(a) for a in args] args2 = [repr(k)+":"+repr(v) for k, v in kwargs.items()] value = func(*args, **kwargs) print("calling ", func.__name__, " ", repr(args1), " ", repr(args2), " returns ", value) return value return f
  29. REStful Web Services The FastAPI framework is a great example

    of using decorators. @app.get("/") def read_root(message: str = Depends(get_message)): return {"message": message} @app.post("/items/") def create_item(item: dict): return {"item": item}
  30. Caching Data Assuming that we have a function that performs

    expensive operation (e.g. fetches data from a server) we can use a decorator that will provide us with an caching mechanism. from cachetools import cached, LRUCache cache = LRUCache(maxsize=100) @cached(cache) def get_data(*args,**kwargs): # expensive computation return kwargs["x"] * 2 print(get_data(x=100))
  31. CLI Applications Development Using Typer, a library that was developed

    by the same people that develop FastAPI, we can easily develop new CLI applications. import typer application = typer.Typer() @application.command() def shalom(name: str) -> None: print(f"shalom {name}") @application.command() def hola(name: str) -> None: print(f"hola {name}") if __name__ == "__main__": application()
  32. The functools.wraps Decorator Use the functools.wraps decorator for wrapping the

    inner function in order to preserve the meta of the original function. [Nice to Have] from functools import wraps def uppercase(func): @wraps(func) def inner(): print("function name:", func.__name__) data = func() return data.upper() return inner
  33. Arbitrary Arguments Consider using *args and **kwargs in your wrapper

    in order to ensure the decorator works with any function signature. [Must] in most cases
  34. Decorator Documentation The value of proper documentation is well known.

    Don't skip the documentation when developing decorators. [Must]
  35. The SRP Principle SRP stands for Single Responsibility Principle. It

    is the first of five important principles known as SOLID. Keep your decorator focused. Make sure it performs one specific task, and make sure it performs it well. Follow the spirit of the SRP principle. [Must]
  36. Handle Exceptions Properly Make sure your decorator handles possible exceptions

    properly. Don’t let errors leak to the caller. [Must]
  37. Don't Invent The Wheel Consider using other well established libraries

    instead of developing a new one that does the same. [Must]
  38. Type Hinting The explicit type annotations for function parameters and

    returned values make your code easier to understand, help tools like linters and IDEs provide better assistance, and reduce the chance of subtle bugs. Clear type hints make long-term maintenance much simpler. [Must]
  39. Learn from Others Explore decorators that were already developed by

    others. Start with the ones the standard library includes. These decorators might inspire
  40. Step by Step Start with the development of relatively simple

    decorators and make an effort to understand how they work.
  41. Other Programming Languages You can learn and get some excellent

    ideas by overviewing the usability of decorators in other programming languages.
  42. Q&A Thanks for attending my talk :) WhatsApp +972.54.6655837 nana.events

    [email protected] https://linkedin.com/in/lifemichael nana.events prompo.ai https://blog.lifemichael.com Download the code samples at https://tinyurl.com/pythonsummitdecorators Jacado jacado.games jacado.games prompo.ai ngager.pro life michael zindrex.com XtremeJ xtremej.dev XtremeJS xtremejs.dev XtremePython xtremepython.dev XtremeAI xtremeai.dev lifemichael.com meetup.com/lifemichael