Function Copying, Closures & Decorators, in Python - Explained Like You’re Chatting Over Coffee

If you’ve ever found yourself scratching your head while trying to wrap your brain around closures, decorators, or why Python lets you pass functions around like trading cards, you’re not alone.


These concepts are cornerstones of Python’s flexibility. They can seem mysterious at first, but once you get them, you’ll feel like you’ve unlocked a new superpower.


In this article, we’ll demystify:
-What closures are?
– How function copying works!!!
– How decorators work under the hood!!!

First up: Functions are first-class citizens in Python

In Python, functions are first-class citizens-meaning they can be assigned to variables, passed as arguments, store them in data structures, returned from other functions and yes copy them.

 

Yep, just like strings, integers, or lists, if we look at the below code.

 

What just happened here? We actually did not “copy” the function but rather created another reference to the same object.

 

Python functions are objects. Assigning a function to another variable doesn’t duplicate it - it just references the same object in memory.

 

When would you want to copy a function?
• You want to modify a copy without affecting the original (e.g., for monkey-patching or decorators).
• You need to clone behaviour across modules or test environments.
• You’re dynamically generating or modifying functions.

 

Types copy example

If you really need to copy a function:

 

What is happening here?

 

Summary
• Functions in Python are objects copying them means dealing with references.
• You can use types. FunctionType to create a shallow copy.
• Full deep copies are rare and usually unnecessary.
• When in doubt, prefer clean redefinition or wrapping over copying.

 

Closures: Functions with Memory
Imagine you’re at your favourite coffee shop. You order your usual — an Espresso Macchiato. The barista remembers your order and smiles: “The usual?” That memory is exactly what a closure is.
A closure is a function object that “remembers” the variables/values from the enclosing scope where it was created, even after that scope has finished execution / is no longer available.


Core concepts of closures
1. Nested Function: A closure always involves a function defined inside another function.
2. Free Variables: The inner function refers to variables from the outer function.
3. Returning Functions: The outer function returns the inner function.
4. State Preservation: The returned function “remembers” the environment in which it was created.

 

 

The key concept here is a closure. Even though the `make_multiplier` function has finished executing, the returned multiply function which still remembers the value of factor from its enclosing scope, that was active at the time of creation, even after the outer function has finished executing.

 

So double remembers factor = 2, and triple remembers factor = 3.


That’s a closure. A function with an inner function that captures variables from the outer function.


Still, want proof that double actually closed over a variable?

 

 

Why closures are useful
• Data Encapsulation: Closures provide a way to hide data from the global scope while still making it accessible to specific functions.
• Creating Function Factories: As shown in your original example, closures enable creating customised functions.
• Implementing Decorators: Closures are fundamental to Python decorators.

 

Decorators: Fancy Closures That Wrap Functions
Now that we know what closures are, decorators will feel like a natural extension. Decorators are a powerful feature in Python that allow you to modify the behaviour of functions or classes without permanently changing their source code. Let’s explore them in detail.

 

Core Concept
A decorator is a function that takes another function as an argument, adds some functionality, and returns another function. All of this without altering the source code of the original function.
Think of it like putting a present inside a gift box. The gift (original function) is still there but now it’s wrapped in something new.

 

Basic Structure

 

Simple Example
Here’s a basic example of using decorator, that logs when a function is called. Here we use @log_function_call to decorate the greet function to modify the functionality.

 

 

The @ Syntax

The @decorator_name syntax is just syntactic sugar. The below two code snippets are equivalent:

 

 

Decorators with arguments
You can also create decorators that accept arguments:

 

 

Stacking Decorators

You can use multiple decorators for a single function. They are applied from bottom to top:

 

 

Preserving function Metadata

When using decorators, metadata of the original function (like name, docstring) gets lost:

 

 

Practical Use Cases
1. Timing Functions:

 

 

2. Caching Return Values:

 

 

Built-in Decorators
Python has several built-in decorators:


1. @property: Transforms a method into a getter for a property
2. @classmethod: Converts a method to a class method
3. @staticmethod: Converts a method to a static method
4. @abstractmethod: Indicates that the method must be implemented by subclasses

 

Decorators offer a clean and reusable way to modify or enhance the behaviour of functions and classes, making your code more modular and following the DRY (Don’t Repeat Yourself) principle.

 

Final Thoughts
We’ve now covered:
• Function Copying (deep dive into internals)
• Closures (functions with memory)
• Decorators (closures in a fancy outfit)
And we did it with real-world metaphors, detailed code, and just the right amount of nerdy charm.
Got feedback? Want to go deeper into functools, contextlib, generators, classes? Drop a comment I’m always up for more Python conversations!

Anshu is a Senior Data Analyst with passion for everything data and over 20 years of cross-functional experience spanning operations, analytics, reporting, and corporate training in various domains. Having specialised in translating complex data concepts into accessible, actionable knowledge for professionals, stakeholders and students alike. Anshu has a deep routed passion for teaching and mentoring, and has delivered impactful analytics training across global audiences, blending technical depth with business relevance. My work draws on real-world problem-solving using tools like SQL, Excel, Python, Tableau, and Power BI, with a strong focus on data driven decisions, data storytelling, hands-on learning, and curriculum design.

 

https://www.linkedin.com/in/anshubantra

Get In Touch