{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](http://www.upm.es/sfs/Rectorado/Gabinete%20del%20Rector/Logos/UPM/EscPolitecnica/EscUpmPolit_p.gif \"UPM\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Course Notes for Learning Intelligent Systems"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Department of Telematic Engineering Systems, Universidad Politécnica de Madrid, © Carlos A. Iglesias"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Functions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A function is a sequence of statements which performs some kind of task.\n",
    "\n",
    "They have optional parameters and an optional return value. If no return is provided, the default return value is *NoneType*.\n",
    "\n",
    "In Python we cannot overload a function. Functions are just names (variables) and cannot have two implementations at the same time. If you declare twice a function, the second declaration overrides the first one. Nevertheless, we can declare default values or variable arguments, which are the main use of overloading."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sum(a, b):\n",
    "    return a + b\n",
    "c = sum(2,3)\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#keyword parameters\n",
    "d = sum(a=2, b=3)\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greetings():\n",
    "    print('***')\n",
    "    print('hi')\n",
    "    print('***')\n",
    "\n",
    "greetings()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# We can assign a function to a variable. Fun\n",
    "d = greetings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "type(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "type(greetings)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Function documentation\n",
    "The first statement in the body of a function is usually a documentation triple-quoted string, called *docstring*, which can be accessed with function_name.\\__doc__. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def reverse(l):\n",
    "    \"\"\"Receives a list and returns the list in reverse order\"\"\"\n",
    "    return l[::-1]\n",
    "\n",
    "l = [1, 2, 3]\n",
    "d = reverse(l)\n",
    "print(d)\n",
    "print(reverse.__doc__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Default parameters\n",
    "\n",
    "We can define default parameters by assigning a value to a parameter in the function definition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sum(a, b=0):\n",
    "    return a + b\n",
    "print(sum(2))\n",
    "print(sum(2,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Variable number of arguments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#variable number of arguments: *\n",
    "def sum(a, *l):\n",
    "    \"\"\"Sum of a non empty list of arbitrary numbers\"\"\"\n",
    "    total = a\n",
    "    for num in l:\n",
    "        total += num\n",
    "    return total\n",
    "print(sum(1))\n",
    "print(sum(1,2,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Packing \n",
    "l = [1, 2, 3]\n",
    "print(sum(1, *l)) # same than sum(1, 1, 2, 3)\n",
    "\n",
    "t = (4, 4, 4)\n",
    "print(sum(1, *t))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lambda functions\n",
    "\n",
    "Lambda functions are anonymous functions. They are used as mini-functions with abbreviated syntax"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sq(x):\n",
    "    return x**x\n",
    "c = sq(3)\n",
    "print('c', c)\n",
    "\n",
    "# lambda equivalent\n",
    "sq = lambda x : x**x\n",
    "c = sq(3)\n",
    "print('c', c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Formatted output: print\n",
    "\n",
    "\n",
    "The arguments of the print function are the following ones:\n",
    "\n",
    "**print(value1, ..., sep='&nbsp;&nbsp;', end='\\n')**\n",
    "\n",
    "* it can receive a variable number of arguments (value1, value2, ...)\n",
    "* *sep*: separator of values (default: ' ')\n",
    "* *end*: final character (default: new line)\n",
    "\n",
    "In Python2, print was not a function, it was a statement, so it was used without parameters: \n",
    "\n",
    "print x\n",
    "\n",
    "If you want to use the print syntax in Python2, you can import the print function to make it compatible with Python3: \n",
    "\n",
    "from \\__future\\__ import print_fuction "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(1, 2, 3, 4)\n",
    "print(1, 2, 3, 4, sep=',')\n",
    "print(1, 2, 3, 4, sep=',', end=\"#\")\n",
    "print(1, 2, 3, 4, sep='|')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can use [**format**](https://pyformat.info/) for string formatting."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "print('Number: {},{}'.format(1, 2)) #replaces {} inside the string by the arguments of format\n",
    "print('PI #{}#'.format(math.pi))\n",
    "print('PI #{:5.2f}#'.format(math.pi)) # at least 5 characters with two decimals"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Input: input\n",
    "\n",
    "User input can be collected with **input**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "num = input('Enter a number ')\n",
    "print(num)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Licence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The notebook is freely licensed under under the [Creative Commons Attribution Share-Alike license](https://creativecommons.org/licenses/by/2.0/).  \n",
    "\n",
    "© Carlos A. Iglesias, Universidad Politécnica de Madrid."
   ]
  }
 ],
 "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.7.1"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
