function annotation

This commit is contained in:
rasbt 2014-04-20 05:27:04 -04:00
parent c1e9e1b9a6
commit 94577a54ce
2 changed files with 494 additions and 5 deletions

View File

@ -1,7 +1,7 @@
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:ef925e4eaf58c6daf50a495a77d38aa0b02a365dfc972bb5c0174332360b5adb" "signature": "sha256:35f23d6f2bbaa131a262533ed080684ed53fc0260430780f248c09af8c645759"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
@ -69,7 +69,8 @@
"- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n", "- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n", "- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n",
"- [Creating copies of mutable objects](#copy_mutable)\n", "- [Creating copies of mutable objects](#copy_mutable)\n",
"- [Key differences between Python 2 and 3](#python_differences)" "- [Key differences between Python 2 and 3](#python_differences)\n",
"- [Function annotations - What are those `->`'s in my Python code?](#function_annotation)"
] ]
}, },
{ {
@ -1807,6 +1808,7 @@
"source": [ "source": [
"<br>\n", "<br>\n",
"<br>\n", "<br>\n",
"<a name='python_differences'></a>\n",
"## Key differences between Python 2 and 3\n", "## Key differences between Python 2 and 3\n",
"\n", "\n",
"There are some good articles already that are summarizing the differences between Python 2 and 3, e.g., \n", "There are some good articles already that are summarizing the differences between Python 2 and 3, e.g., \n",
@ -2043,6 +2045,15 @@
"metadata": {}, "metadata": {},
"outputs": [] "outputs": []
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Handling exceptions\n",
"\n",
"Also the handling of excecptions has slightly changed in Python 3. Now, we have to use the `as` keyword!"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
@ -2061,11 +2072,266 @@
"... except NameError as err:\n", "... except NameError as err:\n",
"... print(err, '--> our error msg')\n", "... print(err, '--> our error msg')\n",
"... \n", "... \n",
"name 'blabla' is not defined --> our error msg\n" "name 'blabla' is not defined --> our error msg"
], ],
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [] "outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### The `next()` function and `.next()` method\n",
"\n",
"Where you can use both function and method in Python 2.7.5, the `next()` function is all that remain in Python 3!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Python 2\n",
">>> my_generator = (letter for letter in 'abcdefg')\n",
">>> my_generator.next()\n",
"'a'\n",
">>> next(my_generator)\n",
"'b'\n",
"\n",
"# Python 3\n",
">>> my_generator = (letter for letter in 'abcdefg')\n",
">>> next(my_generator)\n",
"'a'\n",
">>> my_generator.next()\n",
"Traceback (most recent call last):\n",
" File \"<stdin>\", line 1, in <module>\n",
"AttributeError: 'generator' object has no attribute 'next'"
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='function_annotation'></a>\n",
"## Function annotations - What are those `->`'s in my Python code?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Have you ever seen any Python code that used colons inside the parantheses of a function definition?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def foo1(x: 'insert x here', y: 'insert x^2 here'):\n",
" print('Hello, World')\n",
" return"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And what about the fancy arrow here?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def foo2(x, y) -> 'Hi!':\n",
" print('Hello, World')\n",
" return"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Q: Is this valid Python syntax? \n",
"A: Yes!\n",
" \n",
" \n",
"Q: So, what happens if I *just call* the function? \n",
"A: Nothing!\n",
" \n",
"Here is the proof!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo1(1,2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo2(1,2) "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**So, those are function annotations ... ** \n",
"- the colon for the function parameters \n",
"- the arrow for the return value \n",
"\n",
"You probably will never make use of them (or at least very rarely). Usually, we write good function documentations below the function as a docstring - or at least this is how I would do it (okay this case is a little bit extreme, I have to admit):"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def is_palindrome(a):\n",
" \"\"\"\n",
" Case-and punctuation insensitive check if a string is a palindrom.\n",
" \n",
" Keyword arguments:\n",
" a (str): The string to be checked if it is a palindrome.\n",
" \n",
" Returns `True` if input string is a palindrome, else False.\n",
" \n",
" \"\"\"\n",
" stripped_str = [l for l in my_str.lower() if l.isalpha()]\n",
" return stripped_str == stripped_str[::-1]\n",
" "
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However, function annotations can be useful to indicate that work is still in progress in some cases. But they are optional and I see them very very rarely.\n",
"\n",
"As it is stated in [PEP3107](http://legacy.python.org/dev/peps/pep-3107/#fundamentals-of-function-annotations):\n",
"\n",
"1. Function annotations, both for parameters and return values, are completely optional.\n",
"\n",
"2. Function annotations are nothing more than a way of associating arbitrary Python expressions with various parts of a function at compile-time.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The nice thing about function annotations is their `__annotations__` attribute, which is dictionary of all the parameters and/or the `return` value you annotated."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo1.__annotations__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 17,
"text": [
"{'y': 'insert x^2 here', 'x': 'insert x here'}"
]
}
],
"prompt_number": 17
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo2.__annotations__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 18,
"text": [
"{'return': 'Hi!'}"
]
}
],
"prompt_number": 18
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**When are they useful?**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Function annotations can be useful for a couple of things \n",
"- Documentation in general\n",
"- pre-condition testing\n",
"- [type checking](http://legacy.python.org/dev/peps/pep-0362/#annotation-checker)\n",
" \n",
"..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
} }
], ],
"metadata": {} "metadata": {}

View File

@ -1,7 +1,7 @@
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:ce4b364bfb6414a1b40e25c6ed5320cec6bdbb11d75ce3e44632fe27504ace7e" "signature": "sha256:35f23d6f2bbaa131a262533ed080684ed53fc0260430780f248c09af8c645759"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
@ -69,7 +69,8 @@
"- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n", "- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
"- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n", "- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)\n",
"- [Creating copies of mutable objects](#copy_mutable)\n", "- [Creating copies of mutable objects](#copy_mutable)\n",
"- [Key differences between Python 2 and 3](#python_differences)" "- [Key differences between Python 2 and 3](#python_differences)\n",
"- [Function annotations - What are those `->`'s in my Python code?](#function_annotation)"
] ]
}, },
{ {
@ -2109,6 +2110,228 @@
"language": "python", "language": "python",
"metadata": {}, "metadata": {},
"outputs": [] "outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<br>\n",
"<br>\n",
"<a name='function_annotation'></a>\n",
"## Function annotations - What are those `->`'s in my Python code?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Have you ever seen any Python code that used colons inside the parantheses of a function definition?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def foo1(x: 'insert x here', y: 'insert x^2 here'):\n",
" print('Hello, World')\n",
" return"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And what about the fancy arrow here?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def foo2(x, y) -> 'Hi!':\n",
" print('Hello, World')\n",
" return"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Q: Is this valid Python syntax? \n",
"A: Yes!\n",
" \n",
" \n",
"Q: So, what happens if I *just call* the function? \n",
"A: Nothing!\n",
" \n",
"Here is the proof!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo1(1,2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World\n"
]
}
],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo2(1,2) "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, World\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**So, those are function annotations ... ** \n",
"- the colon for the function parameters \n",
"- the arrow for the return value \n",
"\n",
"You probably will never make use of them (or at least very rarely). Usually, we write good function documentations below the function as a docstring - or at least this is how I would do it (okay this case is a little bit extreme, I have to admit):"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def is_palindrome(a):\n",
" \"\"\"\n",
" Case-and punctuation insensitive check if a string is a palindrom.\n",
" \n",
" Keyword arguments:\n",
" a (str): The string to be checked if it is a palindrome.\n",
" \n",
" Returns `True` if input string is a palindrome, else False.\n",
" \n",
" \"\"\"\n",
" stripped_str = [l for l in my_str.lower() if l.isalpha()]\n",
" return stripped_str == stripped_str[::-1]\n",
" "
],
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However, function annotations can be useful to indicate that work is still in progress in some cases. But they are optional and I see them very very rarely.\n",
"\n",
"As it is stated in [PEP3107](http://legacy.python.org/dev/peps/pep-3107/#fundamentals-of-function-annotations):\n",
"\n",
"1. Function annotations, both for parameters and return values, are completely optional.\n",
"\n",
"2. Function annotations are nothing more than a way of associating arbitrary Python expressions with various parts of a function at compile-time.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The nice thing about function annotations is their `__annotations__` attribute, which is dictionary of all the parameters and/or the `return` value you annotated."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo1.__annotations__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 17,
"text": [
"{'y': 'insert x^2 here', 'x': 'insert x here'}"
]
}
],
"prompt_number": 17
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo2.__annotations__"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 18,
"text": [
"{'return': 'Hi!'}"
]
}
],
"prompt_number": 18
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**When are they useful?**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Function annotations can be useful for a couple of things \n",
"- Documentation in general\n",
"- pre-condition testing\n",
"- [type checking](http://legacy.python.org/dev/peps/pep-0362/#annotation-checker)\n",
" \n",
"..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
} }
], ],
"metadata": {} "metadata": {}