forked from Pierian-Data/Complete-Python-3-Bootcamp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bb99768
commit da2996b
Showing
2 changed files
with
544 additions
and
0 deletions.
There are no files selected for viewing
272 changes: 272 additions & 0 deletions
272
03-Methods and Functions/.ipynb_checkpoints/07-args and kwargs-checkpoint.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# `*args` and `**kwargs`\n", | ||
"\n", | ||
"Work with Python long enough, and eventually you will encounter `*args` and `**kwargs`. These strange terms show up as parameters in function definitions. What do they do? Let's review a simple function:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"5.0" | ||
] | ||
}, | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(a,b):\n", | ||
" return sum((a,b))*.05\n", | ||
"\n", | ||
"myfunc(40,60)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"This function returns 5% of the sum of **a** and **b**. In this example, **a** and **b** are *positional* arguments; that is, 40 is assigned to **a** because it is the first argument, and 60 to **b**. Notice also that to work with multiple positional arguments in the `sum()` function we had to pass them in as a tuple.\n", | ||
"\n", | ||
"What if we want to work with more than two numbers? One way would be to assign a *lot* of parameters, and give each one a default value." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"6.0" | ||
] | ||
}, | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(a=0,b=0,c=0,d=0,e=0):\n", | ||
" return sum((a,b,c,d,e))*.05\n", | ||
"\n", | ||
"myfunc(40,60,20)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Obviously this is not a very efficient solution, and that's where `*args` comes in.\n", | ||
"\n", | ||
"## `*args`\n", | ||
"\n", | ||
"When a function parameter starts with an asterisk, it allows for an *arbitrary number* of arguments, and the function takes them in as a tuple of values. Rewriting the above function:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"6.0" | ||
] | ||
}, | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(*args):\n", | ||
" return sum(args)*.05\n", | ||
"\n", | ||
"myfunc(40,60,20)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Notice how passing the keyword \"args\" into the `sum()` function did the same thing as a tuple of arguments.\n", | ||
"\n", | ||
"It is worth noting that the word \"args\" is itself arbitrary - any word will do so long as it's preceded by an asterisk. To demonstrate this:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"6.0" | ||
] | ||
}, | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(*spam):\n", | ||
" return sum(spam)*.05\n", | ||
"\n", | ||
"myfunc(40,60,20)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## `**kwargs`\n", | ||
"\n", | ||
"Similarly, Python offers a way to handle arbitrary numbers of *keyworded* arguments. Instead of creating a tuple of values, `**kwargs` builds a dictionary of key/value pairs. For example:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"My favorite fruit is pineapple\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(**kwargs):\n", | ||
" if 'fruit' in kwargs:\n", | ||
" print(f\"My favorite fruit is {kwargs['fruit']}\") # review String Formatting and f-strings if this syntax is unfamiliar\n", | ||
" else:\n", | ||
" print(\"I don't like fruit\")\n", | ||
" \n", | ||
"myfunc(fruit='pineapple')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"I don't like fruit\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"myfunc()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## `*args` and `**kwargs` combined\n", | ||
"\n", | ||
"You can pass `*args` and `**kwargs` into the same function, but `*args` have to appear before `**kwargs`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"I like eggs and spam and my favorite fruit is cherries\n", | ||
"May I have some orange juice?\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"def myfunc(*args, **kwargs):\n", | ||
" if 'fruit' and 'juice' in kwargs:\n", | ||
" print(f\"I like {' and '.join(args)} and my favorite fruit is {kwargs['fruit']}\")\n", | ||
" print(f\"May I have some {kwargs['juice']} juice?\")\n", | ||
" else:\n", | ||
" pass\n", | ||
" \n", | ||
"myfunc('eggs','spam',fruit='cherries',juice='orange')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Placing keyworded arguments ahead of positional arguments raises an exception:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"ename": "SyntaxError", | ||
"evalue": "positional argument follows keyword argument (<ipython-input-8-fc6ff65addcc>, line 1)", | ||
"output_type": "error", | ||
"traceback": [ | ||
"\u001b[1;36m File \u001b[1;32m\"<ipython-input-8-fc6ff65addcc>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m myfunc(fruit='cherries',juice='orange','eggs','spam')\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"myfunc(fruit='cherries',juice='orange','eggs','spam')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"As with \"args\", you can use any name you'd like for keyworded arguments - \"kwargs\" is just a popular convention.\n", | ||
"\n", | ||
"That's it! Now you should understand how `*args` and `**kwargs` provide the flexibilty to work with arbitrary numbers of arguments!" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"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.6.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.