Skip to content

Instantly share code, notes, and snippets.

@xarical
Last active April 19, 2025 19:17
Show Gist options
  • Select an option

  • Save xarical/32673b18c98517bc08130ffdf8a1dc37 to your computer and use it in GitHub Desktop.

Select an option

Save xarical/32673b18c98517bc08130ffdf8a1dc37 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"authorship_tag": "ABX9TyOOEXPtm9JONiG5qS1O6+9g",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": { "id": "view-in-github", "colab_type": "text" },
"source": [
"<a href=\"https://colab.research.google.com/gist/xarical/32673b18c98517bc08130ffdf8a1dc37/function_decorators.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# <u> Function decorators </u>\n",
"Function decorators allow us to modify the behavior of a function without modifying the function itself."
],
"metadata": {
"id": "Al1bkKS-nA0g"
}
},
{
"cell_type": "markdown",
"source": [
"\n",
"\n",
"---\n",
"\n"
],
"metadata": {
"id": "_vUpxLtiomMT"
}
},
{
"cell_type": "markdown",
"source": [
"This is how you use a decorator:"
],
"metadata": {
"id": "WYHK0xoygSe2"
}
},
{
"cell_type": "code",
"source": [
"def decorator(func):\n",
" \"\"\"\n",
" Prints \"before\" before running func(), \"after\" after running func(),\n",
" and then returns the return from func() using any *args and **kwargs\n",
" passed in.\n",
"\n",
" It works by returning a new_func() function that wraps the original\n",
" function (which is passed in as the parameter \"func\")\n",
" \"\"\"\n",
"\n",
" def new_func(*args, **kwargs):\n",
" print(\"before\")\n",
" result = func(*args, **kwargs)\n",
" print(\"after\")\n",
" return result\n",
"\n",
" return new_func\n",
"\n",
"def calculate_sum(a, b):\n",
" \"\"\"\n",
" This is the original function. It prints \"inside\" and then returns the\n",
" sum of the parameters.\n",
" \"\"\"\n",
"\n",
" print(\"inside\")\n",
" return a + b\n",
"\n",
"# Assigning calculate_sum to the function returned by decorator(calculate_sum)\n",
"# It works, but there's a better way to do this...\n",
"calculate_sum = decorator(calculate_sum)\n",
"\n",
"# Calling the new calculate_sum\n",
"print(\"sum =\", calculate_sum(1, 1))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "a46ee312-4005-4bf1-fbae-e1691c75e790",
"id": "NARpX33WnA0h"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"before\n",
"inside\n",
"after\n",
"sum = 2\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"It works, but there's a better way to do this. You can instead use decorator syntax."
],
"metadata": {
"id": "cn_ELY2fhOAN"
}
},
{
"cell_type": "code",
"source": [
"def decorator(func):\n",
" \"\"\"\n",
" This is the same decorator function from earlier. Nothing has changed\n",
" \"\"\"\n",
"\n",
" def new_func(*args, **kwargs):\n",
" print(\"before\")\n",
" result = func(*args, **kwargs)\n",
" print(\"after\")\n",
" return result\n",
"\n",
" return new_func\n",
"\n",
"@decorator\n",
"def calculate_sum(a, b):\n",
" \"\"\"\n",
" This is the same original function from earlier, BUT using decorator\n",
" syntax (the @decorator on top)\n",
" \"\"\"\n",
"\n",
" print(\"inside\")\n",
" return a + b\n",
"\n",
"print(\"sum =\", calculate_sum(1, 1))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "4e945f6a-54a3-4791-fb7f-f25376331290",
"id": "qB5D0PzSnA0i"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"before\n",
"inside\n",
"after\n",
"sum = 2\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"The output is the same, but instead of `calculate_sum = decorator(calculate_sum)` after the original function, you write `@decorator` on top of it. It looks nicer and is more organized."
],
"metadata": {
"id": "o3C4ODeFhRrx"
}
},
{
"cell_type": "markdown",
"source": [
"\n",
"\n",
"---\n",
"\n"
],
"metadata": {
"id": "eCy0mZ_Moi8z"
}
},
{
"cell_type": "markdown",
"source": [
"Example: A decorator that makes the *args passed to the function lowercase\n"
],
"metadata": {
"id": "-w2go3_BnA0j"
}
},
{
"cell_type": "code",
"source": [
"def lowercase_user_input(func):\n",
" \"\"\"\n",
" This function prints the result of func() if the *args was all lowercase.\n",
"\n",
" It works the same as the decorator() function from earlier; it returns a\n",
" lowercase_func() function that wraps the original function (which, like earlier,\n",
" is passed in as the parameter \"func\")\n",
" \"\"\"\n",
"\n",
" def lowercase_func(*args):\n",
" lowercase_args = [arg.lower() for arg in args]\n",
" result = func(*lowercase_args)\n",
" return result\n",
"\n",
" return lowercase_func\n",
"\n",
"# Now we can make many functions, and easily have them convert any arguments into\n",
"# lowercase just by adding @lowercase_user_input at the top.\n",
"@lowercase_user_input\n",
"def handle_user_input(input):\n",
" \"\"\"\n",
" This function returns True if the input is y, and False if it is n.\n",
" \"\"\"\n",
"\n",
" if input == \"y\":\n",
" return True\n",
" elif input == \"n\":\n",
" return False\n",
" else:\n",
" return \"Invalid input\"\n",
"\n",
"# more functions using @lowercase_user_input here...\n",
"\n",
"user_input = input(\"Enter y or n (not case sensitive): \")\n",
"print(\"User input is y:\", handle_user_input(user_input))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "9118f5a2-4698-46f6-c514-8154fafabfa2",
"id": "E_Ebgx98nA0j"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Enter y or n (not case sensitive): Y\n",
"User input is y: True\n"
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment