Skip to content

Instantly share code, notes, and snippets.

@manuelinfosec
Last active September 6, 2022 04:04
Show Gist options
  • Save manuelinfosec/ab0f5ae0b84bf83849cd55e4839dd508 to your computer and use it in GitHub Desktop.
Save manuelinfosec/ab0f5ae0b84bf83849cd55e4839dd508 to your computer and use it in GitHub Desktop.
ab0f5ae0b84bf83849cd55e4839dd508
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/manuelinfosec/ab0f5ae0b84bf83849cd55e4839dd508/python-decorator-for-dummies.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mGxVwdM7sjfc"
},
"source": [
"## Python Decorators For Dummies\n",
"> The Best Explanation You Can Ever Find"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Rdl4sAsssjfk"
},
"outputs": [],
"source": [
"import discord\n",
"client = discord.Client(intents=intents)\n",
"\n",
"@client.event # take note of this line\n",
"async def on_ready():\n",
" print(f\"Logged in as {client.user}\")\n",
"\n",
"@client.event # take note of this line\n",
"async def on_message(msg):\n",
" if msg.content == \"\":\n",
" pass\n",
"# ... SOME MORE CODE ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "VjLllYe9sjfn"
},
"source": [
"### A simple Python function"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "U-Xd6p_Xsjfo",
"outputId": "b4f87cc9-2e13-48cd-d875-055329a229d8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Yes!\n"
]
}
],
"source": [
"def shout(word='yes'):\n",
" return word.capitalize() + '!'\n",
"\n",
"print(shout())"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LF6kuKlYsjfp"
},
"source": [
"### Python function assigned to a variable"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ybu5aaAqsjfr"
},
"outputs": [],
"source": [
"scream = shout"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iEnrIZAosjfs"
},
"source": [
"### Calling the function from a variable"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ZhhslIrlsjft",
"outputId": "0b446ef0-3618-4dc7-db1c-5d0d9b085335"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Yes!\n"
]
}
],
"source": [
"print(scream())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "CVRVzKPusjfw",
"outputId": "d4e5bb9c-2db2-472f-f422-f8c991053d23"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"name 'shout' is not defined\n",
"Yes!\n"
]
}
],
"source": [
"# deleting the shout() object\n",
"del shout\n",
"\n",
"try:\n",
"\t# trying to access the deleted shout() object\n",
" print(shout())\n",
"except NameError as e:\n",
" print(e)\n",
"\n",
"print(scream())"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cuggh3Bisjfy"
},
"source": [
"### Defining functions within functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "jGJAbWaXsjfz",
"outputId": "abe579b2-13d3-49ce-fc19-daeb55c07f41"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"yes...\n"
]
}
],
"source": [
"def talk():\n",
" # Defining a function on the fly in `talk` ...\n",
" def whisper(word='yes'):\n",
" return word.lower() + '...'\n",
" # ... and using it right away!\n",
" print(whisper())\n",
"\n",
"talk()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pxMRA9o_sjf0"
},
"source": [
"### Internal functions don't exist beyond their scope"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "lvS6hoqFsjf1",
"outputId": "4d4744ce-96ff-4ab7-c7b6-53fe701c67c0"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"name 'whisper' is not defined\n"
]
}
],
"source": [
"try:\n",
" print(whisper())\n",
"except NameError as e:\n",
" print(e)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PIHporl1sjf2"
},
"source": [
"### Function returning function"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "zbYkp9h5sjf3"
},
"outputs": [],
"source": [
"def getTalk(kind='shout'):\n",
" # We define functions on the fly\n",
" def shout(word='yes'):\n",
" return word.capitalize() + '!'\n",
"\n",
" def whisper(word='yes'):\n",
" return word.lower() + '...'\n",
"\n",
" # Then we return one of them\n",
" if kind == 'shout':\n",
"\t # What happened here?\n",
" return shout \n",
" else:\n",
" return whisper"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RNAnCm_Rsjf3"
},
"source": [
"### Driver code for the previous cell"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "e4VRNki_sjf4",
"outputId": "1b45b3dc-6a4a-4121-b2a2-75f5cd43a3b0"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<function getTalk.<locals>.shout at 0x000001C34384AA60>\n",
"Yes!\n",
"yes...\n"
]
}
],
"source": [
"# Get the function and assign it to a variable\n",
"talk = getTalk() \n",
"\n",
"# You can see that `talk` is here a function object:\n",
"print(talk)\n",
"\n",
"# The object is the one returned by the function:\n",
"print(talk())\n",
"\n",
"# And you can even use it directly if you feel wild:\n",
"print(getTalk('whisper')())"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Qv82FZOtsjf5"
},
"source": [
"### Passing a function as parameter"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "w_8i5ERvsjf5",
"outputId": "15314c08-cb6e-4202-d084-5b8777768e50"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"I do something before then I call the function you gave me\n",
"Yes!\n"
]
}
],
"source": [
"def doSomethingBefore(func): \n",
" print(\"I do something before then I call the function you gave me\")\n",
" print(func())\n",
"\n",
"doSomethingBefore(scream)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "CD6SMYzqsjf6"
},
"source": [
"### Python Decorators The Hard Way"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "G7de6AgRsjf7"
},
"outputs": [],
"source": [
"def my_shiny_new_decorator(a_function_to_decorate):\n",
" # Inside, the decorator defines a function on the fly: the wrapper.\n",
" # This function is going to be wrapped around the original function\n",
" # so it can execute code before and after it.\n",
" def the_wrapper_around_the_original_function():\n",
" \n",
" # Put here the code you want to be executed BEFORE the original \n",
" # function is called\n",
" print(\"Before the function runs\")\n",
"\n",
" # Call the function from the parameter here (using parentheses)\n",
" a_function_to_decorate()\n",
"\n",
" # Put here the code you want to be executed AFTER the original \n",
" # function is called\n",
" print(\"After the function runs\")\n",
"\n",
" # At this point, `a_function_to_decorate` HAS NEVER BEEN EXECUTED.\n",
" # We return the wrapper function we have just created.\n",
" # The wrapper contains the function and the code to execute before\n",
" # ...and after. It’s ready to use!\n",
" return the_wrapper_around_the_original_function"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "63S9myZYsjf9"
},
"source": [
"### Creating a standalone function"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "i700wFeBsjf-",
"outputId": "88e27dfe-a4cf-430d-a0fd-293c863376c7"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"I am a stand alone function, don’t you dare modify me\n"
]
}
],
"source": [
"def a_stand_alone_function():\n",
" print(\"I am a stand alone function, don’t you dare modify me\")\n",
"\n",
"a_stand_alone_function() "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gmZgE-jssjgB"
},
"source": [
"### Wrapping the standalone function around a decorator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "npOsRV7ysjgB",
"outputId": "f63ad3d6-5c71-42d2-dab7-45cea4b24946"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Before the function runs\n",
"I am a stand alone function, don’t you dare modify me\n",
"After the function runs\n"
]
}
],
"source": [
"a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)\n",
"a_stand_alone_function_decorated()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "gZlefn6msjgC",
"outputId": "085b7f8a-ce4b-4bb9-b1b1-dfa838861637"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Before the function runs\n",
"I am a stand alone function, don’t you dare modify me\n",
"After the function runs\n"
]
}
],
"source": [
"a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)\n",
"a_stand_alone_function()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jRpQxVgnsjgC"
},
"source": [
"### Python decorators the Pythonic way"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "uPL6y1NksjgD",
"outputId": "9c53013f-1884-4bd5-a53b-d01bdcd932e4"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Before the function runs\n",
"Leave me alone\n",
"After the function runs\n"
]
}
],
"source": [
"@my_shiny_new_decorator\n",
"def another_stand_alone_function():\n",
" print(\"Leave me alone\")\n",
"\n",
"another_stand_alone_function()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0X560t5csjgD"
},
"outputs": [],
"source": [
"another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3rBmaLm6sjgD"
},
"source": [
"### A better example of Python decorators the naive way"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "joP54vcAsjgD",
"outputId": "95bc361d-8f45-42af-bec3-e5869dba59b3"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--ham--\n",
"</''''''\\>\n",
"#tomatoes#\n",
"--ham--\n",
"~salad~\n",
"<\\______/>\n"
]
}
],
"source": [
"def bread(func):\n",
" def wrapper():\n",
" print(\"</''''''\\>\")\n",
" func()\n",
" print(\"<\\______/>\")\n",
" return wrapper\n",
"\n",
"def ingredients(func):\n",
" def wrapper():\n",
" print(\"#tomatoes#\")\n",
" func()\n",
" print(\"~salad~\")\n",
" return wrapper\n",
"\n",
"def sandwich(food='--ham--'):\n",
" print(food)\n",
"\n",
"sandwich()\n",
"print()\n",
"# Outputs: --ham--\n",
"\n",
"sandwich = bread(ingredients(sandwich))\n",
"# sandwich is now reference to the decorator\n",
"# instead of the `--ham` string.\n",
"sandwich()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1ozDjNTpsjgE"
},
"source": [
"### Python decorators the Pythonic way"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "szhOZ9LwsjgE",
"outputId": "b70b4f0d-479d-4426-9f2e-55cf85a89465"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"</''''''\\>\n",
"#tomatoes#\n",
"--ham--\n",
"~salad~\n",
"<\\______/>\n"
]
}
],
"source": [
"@bread\n",
"@ingredients\n",
"def sandwich(food=\"--ham--\"):\n",
"\tprint(food)\n",
"\n",
"sandwich()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wrnNHzBxsjgF"
},
"source": [
"### Unordered decorators"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "yiOe9xXVsjgF",
"outputId": "b9cd28cb-73f4-4300-9e05-5f60bdbf84a8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"#tomatoes#\n",
"</''''''\\>\n",
"--ham--\n",
"<\\______/>\n",
"~salad~\n"
]
}
],
"source": [
"@ingredients\n",
"@bread\n",
"def strange_sandwich(food='--ham--'):\n",
" print(food)\n",
"\n",
"strange_sandwich()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.9.4 64-bit",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.4"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "82ed002fa2d4956f5c6aec99bcefe0f73a9f79882f3c9e2319b14958a5896ac5"
}
},
"colab": {
"provenance": [],
"include_colab_link": true
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment