{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](img/logocurso.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "d9e822f9-0a52-43f2-90ef-e8fd6860aacc"
    }
   },
   "source": [
    "![](img/sesion3.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Variables y argumentos: filosofía de Python\n",
    "\n",
    "En Python es preciso definir una variable antes de utilizarla. Si intentamos trabajar con una variable que no ha sido definida se producirá un mensaje de error."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Pidamos a Python que muestre una variable que no ha sido definida con anterioridad\n",
    "amigos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Por tanto el paso inicial para utilizar una variable es definirla mediante una operación de asignación. La asignación, ya lo sebemos, se realiza mediante operador de asignación **=**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Después de definir la variable mediante una asignación podremos utilizarla sin ningún problema.\n",
    "amigos=[\"Pepe\",\"Paco\",\"Pepa\"]\n",
    "len(amigos)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pero qué es realmente una variable, qué acciones realiza Python para crearla cuando ejecutamos una asignación. La creación de la variable implica tres elementos fundamentales:\n",
    "* El objeto que pretendemos utilizar para dar valor a la variable.\n",
    "* El símbolo o nombre de la variable.\n",
    "* La referencia que conecta el símbolo con el objeto.\n",
    "\n",
    "Cuando ejecutamos una asignación como \n",
    "<div align='center'><b>amigos</b> = [\"Pepe\",\"Paco\",\"Pepa\"]</div>\n",
    "Python automáticamente ejecuta las siguientes acciones:\n",
    "<ol>\n",
    "    <li>Calcula y crea el objeto especificado a la derecha del <b>=</b> y lo sitúa en la memoria en una posición concreta.</li>\n",
    "<li>Añade la variable a la tabla de símbolos actual insertando su nombre o símbolo y una referencia que conecta ese símbolo con la ubicación de memoria en la que se ha creado el objeto en el paso anterior.</li>\n",
    "</ol>\n",
    "<div class=\"alert alert-info\">En realidad el único valor que almacena la variable es la referencia al objeto. El objeto en sí existe independientemente en un lugar concreto de la memoria.</div>\n",
    "\n",
    "Cuando se copia una variable en otra mediante\n",
    "<div align='center'><b>amigoscop</b> = <b>amigos</b></div>\n",
    "lo único que se hace es insertar en la tabla de símbolos una nueva variable en la que se copia la misma referencia que contiene <b>amigos</b> al objeto que se creo antes sin que se construya ningún objeto nuevo para la nueva variable.\n",
    "\n",
    "![](img/sesion3-variables-01.png)\n",
    "\n",
    "Por tanto, ambas variables <b>amigos</b> y <b>amigoscop</b> apuntan al mismo objeto. Si el objeto es mutable (como listas, diccionarios, conjuntos) podremos acceder a el, manejarlo y modificarlo utilizando cualquiera de las dos variables. Ambas variables muestran el mismo objeto así que los cambios que realicemos utilizando una se verán reflejados también con la otra"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Creamos una nueva variable en la que copiamos la inicial. Simplemente se copiará la referencia.\n",
    "amigoscop=amigos\n",
    "# Tendremos dos variables que referencian a un único objeto (la lista [\"Pepe\",\"Paco\",\"Pepa\"]).\n",
    "# Las listas son objetos mutables así que el objeto podremos modificarlo empleando ambas variables \n",
    "amigoscop[2]=\"Francisco\"\n",
    "# Puesto que amigoscop y amigos referencian la misma lista, amigos cop mostrará el cambio realizado usando amigoscop.\n",
    "amigos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "Si ahora realizamos una nueva asignación para **amigos** con un nuevo objeto,\n",
    "<div align='center'>amigos = 3</div>\n",
    "se creará en la memoria el nuevo objeto (el número 3) y se modificará la referencia de <b>amigos</b> para que apunte a él. El antiguo objeto lista (es decir, [\"Pepe\",\"Paco\",\"Pepa\"]) permanecerá en memoria solamente si está referenciado por alguna variable y en caso contrario será destruido."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "amigos=3\n",
    "# Se crea un nuevo objeto (el número 3) que será referenciado por amigos. El objeto lista inicial sigue existiendo ya que\n",
    "# está referenciado por amigoscop\n",
    "print(amigos)\n",
    "print(amigoscop)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Si también asignamos a amigoscop un nuevo objeto, la lista será destruida ya que ninguna variable la referencia.\n",
    "amigoscop=\"hola como estás\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">El objeto que se utiliza en una asignación se calcula únicamente una vez de forma inmediata en el momento de producirse la asignación con los valores activos en ese punto.</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x=3\n",
    "y=x+1### Ejercicio 1\n",
    "Pesar antes de ejecutar. ¿Que resultados se imprimirán?\n",
    "print(\"y =\",y)\n",
    "x=5\n",
    "print(\"y tras modificar x =\",y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 1\n",
    "Pesar antes de ejecutar. ¿Que resultados se imprimirán?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lista=[1,2,3]\n",
    "listacopia=lista\n",
    "listacopia.append(4)\n",
    "print(\"lista=\",lista)\n",
    "print(\"listacopia=\",listacopia)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lista=[1,2,3]\n",
    "listacopia=lista+[4]\n",
    "print(\"lista=\",lista)\n",
    "print(\"listacopia=\",listacopia)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 2\n",
    "Si definimos lista=[1,2,3], ¿cómo definir una nueva variable listacopia con el mismo valor que lista pero que pueda modificarse independientemente (que los cambios sobre listacopia, como listacopia.append(4) no afecten a lista)?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Variables locales y globales\n",
    "\n",
    "En Python podemos trabajar en varios contextos simultáneamente y cada contexto tiene su propia tabla de símbolos, es decir, sus propias variables. Más adelante cuando hablemos de módulos daremos una idea más precisa de lo que es un contexto pero por ahora nos basta con tomar como ejemplo las funciones.\n",
    "\n",
    "<div class=\"alert alert-info\">Cada función tiene su propio contexto local y su propia tabla de símbolos local.\n",
    "<ul>\n",
    "<li>Las variables definidas dentro de la función son locales y forman parte de la tabla de símbolos local de la función. Fuera de ellas no son accesibles.</li>\n",
    "<li>Las variables definidas fuera de la función (en el contexto superior a la función) son globales y son accesibles tanto fuera como dentro de las funciones y contextos inferiores.</li>\n",
    "<li>Si dentro de una función se define una variable local con el mismo nombre que otra global, tendrá prioridad la local.</li>\n",
    "<li>Dentro de una función puede definirse una variable global (accesible fuera de la función) utilizando la declaración <b>global</b>.</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n=3\n",
    "m=4\n",
    "def funprueba():\n",
    "    ndentro=10\n",
    "    global nfuera\n",
    "    nfuera=10\n",
    "    m=23\n",
    "    print(\"Dentro de funprueba, n (global) es visible:\",n)\n",
    "    print(\"Dentro de funprueba, tiene prioridad la variable m local:\",m)\n",
    "    return\n",
    "funprueba()\n",
    "print(\"nfuera es global y se puede utilizar fuera de funprueba:\",nfuera)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ndentro es local y no se puede utilizar fuera de funprueba\n",
    "ndentro"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Paso por referencia y paso por valor\n",
    "\n",
    "En python el paso de variables a las funciones es siempre por referencia. Es decir, cuando se pasa un objeto a una función como argumento, no se realiza una copia de ese objeto, se trabaja directamente sobre el y las modificaciones dentro de la función afectarán al objeto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "listafuera=[\"pata\",\"peta\",\"pita\"]\n",
    "print(\"antes de la función:\",listafuera)\n",
    "\n",
    "def cambialista(lista):\n",
    "    lista[2]=\"troloronlonlon\"\n",
    "    return\n",
    "\n",
    "cambialista(listafuera)\n",
    "\n",
    "print(\"después de la función:\",listafuera)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 3\n",
    "Pesar antes de ejecutar. ¿Que resultados se imprimirán?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def misterio(a,L=[]):\n",
    "    L.append(a)\n",
    "    return L\n",
    "\n",
    "print(misterio(1))\n",
    "print(misterio(2))\n",
    "print(misterio(3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 4\n",
    "Pensar antes de ejecutar. ¿Que resultado se imprimira?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y=10\n",
    "def misterio2(x=y):\n",
    "    return x\n",
    "\n",
    "print(misterio2())\n",
    "y=20\n",
    "print(misterio2())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Módulos\n",
    "\n",
    "Un módulo es un fichero con extensión .py que puede contener instrucciones, funciones, clases, etc. Las definiciones de un módulo forman su contexto local. Esas definiciones pueden utilizarse importando dicho módulo mediante:\n",
    "<div align='center'>import nombremodulo</div>\n",
    "Cuando se importa un módulo se producen los siguientes efectos:\n",
    "<ul>\n",
    "<li>El nombre del módulo se incorpora a la tabla de símbolos del módulo que lo llama. El módulo raíz o principal se denomina <b>&#95;&#95;main&#95;&#95;</b>. El nombre de un módulo se puede obtener con <b>&#95;&#95;name&#95;&#95;</b>.</li>\n",
    "<li>Se crea una tabla de símbolos propia para el módulo importado.</li>\n",
    "<li>Se ejecutan las instrucciones del módulo (una sola vez, la primera vez que se le llama desde algún punto). </li>\n",
    "<li>Las definiciones del módulo importado no se incorporan a la tabla de símbolos del que lo llama pero pueden utilizarse mediante notación de objetos:\n",
    "<div align='center'>nombremodulo.definicion</div>\n",
    "o también, en cascada, de forma encadenada:\n",
    "<div align='center'>nombremodulo.nombresubmodulo.nombresubsubmodulo.definicion.</div>\n",
    "Depende desde qué punto se haya importado un módulo, sus definiciones podrían ser accesibles utilizando diferentes rutas. En cualquier caso, la ejecución y creación de objetos tiene lugar una única vez.\n",
    "</li>\n",
    "</ul>\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "Algunas cuestiones de interés:\n",
    "<ul>\n",
    "<li>Es posible importar varios módulos utilizando la sintaxis:\n",
    "<div align='center'>import modulo1, modulo2, modulo3,...</div></li>\n",
    "<li>Es posible importar una definición concreta de un módulo en lugar del módulo completo mediante:\n",
    "<div align='center'>form modulo import definicion1, definicion2,...</div>\n",
    "También podemos importar todas las definiciones del módulo con:\n",
    "<div align='center'>from modulo import *</div>\n",
    "En tal caso las definiciones importadas se incorporan al contexto actual y pueden utilizarse directamente sin notación de \n",
    "módulos.</li>\n",
    "<li>Podemos visualizar la tabla de símbolos (lista de variables y definiciones) de un módulo con\n",
    "<div align='center'>dir(modulo)</div></li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 5\n",
    "Crear los siguientes módulos:\n",
    "* módulo **matemamio.py** que incluya las funciones **sumatotal** y **productototal** y **potenciatotal** que calculen la suma, producto y potencia de una cantidad cualquiera de números.\n",
    "* módulo **cadenamio.py** que incluya una función **juntatodo** que concatene una cantidad cualquiera de cadenas de texto.\n",
    "* módulo **paises.py** que contenga una lista llamada **cadenapaises** con los países que he visitado y que imprima esa cadena.\n",
    "* módulo **libros.py**  que contenga una lista llamada **cadenalibros** con los libros que he leído y que imprima esa cadena.\n",
    "* módulo **cientifico.py** que importe a los módulos **matemamio.py** y **cadenamio.py**.\n",
    "* módulo **romantico.py** que importe a los módulos **paises.py** y **libros.py**\n",
    "* módulo **total.py** que importe a **cientifico.py** y **romantico.py**.\n",
    "\n",
    "<ol>\n",
    "    <li>Importar el módulo <b>total.py</b> con spyder. Utilizar las funciones incluidas en matemamio.py/cadenamio.py e imprimir las listas de paises.py/libros.py</li>\n",
    "<li>Importar el módulo <b>cientifico.py</b> y utilizar las funciones contenidas en matemamio.py/cadenamio.py.</li>\n",
    "<li>Importar el módulo <b>matemamio.py</b> y tulizar las funciones contenidas en el.\n",
    "    <li>Importar directamente la definicion de <b>sumatotal</b> y <b>productototal</b> para que se puedan utilizar sin notación de submódulos.\n",
    "</ol>\n",
    "En todos los casos, estudiar cómo puedo acceder a <b>sumatotal</b> y <b>juntatodo</b> dependiendo del modo en que se importaron los módulos.\n",
    "\n",
    "<b>Este ejercicio debe realizarse en spyder</b>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ficheros\n",
    "\n",
    "Desde python es posible abrir, modificar y guardas ficheros. El mecanismo para manejar un fichero involucra los siguientes pasos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\">\n",
    "<ul>\n",
    "<li>variablefichero=open(\"nombrefichero\",\"modo\")  <---- Se abre el fichero para iniciar su uso.</li>\n",
    "<li>instrucciones lectura/escritura               <---- Se opera sobre el.</li>\n",
    "<li>variablefichero.close()                       <---- Se cierra para liberar recurso.</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los modos que podemos utilizar son los siguientes:\n",
    "* **w**: Modo de escritura. Crea un ficheo y permite en el que podremos escribir datos. Si el fichero ya existía será sobrescrito.\n",
    "* **r**: Modo de lectura. Permite leer los datos de un fichero existente.\n",
    "* **r+**: Modo lectura/escritura. Permite tanto leer como añadir información al fichero.\n",
    "* **a**: Modo de adición. Si el fichero existe permite añadir más información al final y en caso de no existir lo creará.\n",
    "* **rb**, **r+b**: Permite modo binario de lectura escritura."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fichero=open(\"ficherofrases.txt\",\"r\")\n",
    "\n",
    "frase1=fichero.readline()\n",
    "frase2=fichero.readline()\n",
    "print(frase1)\n",
    "print(frase2)\n",
    "fichero.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "<div class=\"alert alert-info\">Disponemos de las siguientes instrucciones de lectura/escritura:\n",
    "<ul>\n",
    "<li><b>.write('cadena')</b>: Escribe una cadena en el fichero</li>\n",
    "<li><b>.read()</b>: Lee todo el fichero.</li>\n",
    "    <li><b>.read(n)</b>: Lee <b>n</b> bytes del fichero.</li>\n",
    "<li><b>.readline()</b>: Lee una línea del fichero (separador \"\\n\").</li>\n",
    "<li><b>.readlines()</b>: Lee todas las líneas del fichero.</li>\n",
    "<li><b>.tells()</b>: Proporciona la posición actual de lectura/escritura.</li>\n",
    "<li><b>.seek(pos,modo)</b>: Mueve la posición actual el número de bytes indicado por <b>pos</b> según se especifique en <b>modo</b> (modo=0, desde el principio (por defectoa), modo=1, desde la posición actual, modo=2, desde el final).</li>\n",
    "</ul>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fichero=open(\"ficherofrases.txt\",\"r\")\n",
    "\n",
    "# Lee 10 bytes\n",
    "fragmento=fichero.read(10)\n",
    "print(fragmento)\n",
    "\n",
    "fichero.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fichero=open(\"ficherofrases.txt\",\"r\")\n",
    "\n",
    "# Se desplaza 10 bytes y lee los diez siguientes\n",
    "fichero.seek(10)\n",
    "fragmento=fichero.read(10)\n",
    "print(fragmento)\n",
    "\n",
    "fichero.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fichero=open(\"ficherofrases.txt\",\"r\")\n",
    "\n",
    "# Almacena todas las líneas del texto en una lista.\n",
    "lineas=fichero.readlines()\n",
    "for linea in lineas:\n",
    "    print(linea)\n",
    "\n",
    "fichero.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 6\n",
    "Crea un archivo denominado \"misdatos.txt\" en el que incluirás en diferentes línea tu nombre, dni, titulación y dirección."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 7\n",
    "Acceder al archivo creado anteriormente y añadir dos líneas más indicando lugar de nacimiento y estado civil."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 8\n",
    "Acceder al fichero anterior, modificar la titulación por la del compañero contiguo y guardar la nueva información en otro fichero con nombre diferente."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
