Skip to content

Commit

Permalink
added args and kwargs
Browse files Browse the repository at this point in the history
  • Loading branch information
TiVentures committed Feb 13, 2018
1 parent bb99768 commit da2996b
Show file tree
Hide file tree
Showing 2 changed files with 544 additions and 0 deletions.
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
}
Loading

0 comments on commit da2996b

Please sign in to comment.