{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Trabajando con clases heredadas en conjunto"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Producto:\n",
    "    def __init__(self,referencia,nombre,pvp,descripcion):\n",
    "        self.referencia = referencia\n",
    "        self.nombre = nombre\n",
    "        self.pvp = pvp\n",
    "        self.descripcion = descripcion\n",
    "        \n",
    "    def __str__(self):\n",
    "        return \"\"\"\\\n",
    "REFERENCIA\\t{}\n",
    "NOMBRE\\t\\t{}\n",
    "PVP\\t\\t{}\n",
    "DESCRIPCIÓN\\t{}\"\"\".format(self.referencia,self.nombre,self.pvp,self.descripcion)\n",
    "    \n",
    "\n",
    "class Adorno(Producto):\n",
    "    pass\n",
    "\n",
    "\n",
    "class Alimento(Producto):\n",
    "    productor = \"\"\n",
    "    distribuidor = \"\"\n",
    "    \n",
    "    def __str__(self):\n",
    "        return \"\"\"\\\n",
    "REFERENCIA\\t{}\n",
    "NOMBRE\\t\\t{}\n",
    "PVP\\t\\t{}\n",
    "DESCRIPCIÓN\\t{}\n",
    "PRODUCTOR\\t{}\n",
    "DISTRIBUIDOR\\t{}\"\"\".format(self.referencia,self.nombre,self.pvp,self.descripcion,self.productor,self.distribuidor)\n",
    "\n",
    "\n",
    "class Libro(Producto):\n",
    "    isbn = \"\"\n",
    "    autor = \"\"\n",
    "    \n",
    "    def __str__(self):\n",
    "        return \"\"\"\\\n",
    "REFERENCIA\\t{}\n",
    "NOMBRE\\t\\t{}\n",
    "PVP\\t\\t{}\n",
    "DESCRIPCIÓN\\t{}\n",
    "ISBN\\t\\t{}\n",
    "AUTOR\\t\\t{}\"\"\".format(self.referencia,self.nombre,self.pvp,self.descripcion,self.isbn,self.autor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Creamos algunos objetos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ad = Adorno(2034,\"Vaso adornado\",15,\"Vaso de porcelana adornado con árboles\")\n",
    "\n",
    "al = Alimento(2035,\"Botella de Aceite de Oliva Extra\",5,\"250 ML\")\n",
    "al.productor = \"La Aceitera\"\n",
    "al.distribuidor = \"Distribuciones SA\"\n",
    "\n",
    "li = Libro(2036,\"Cocina Mediterránea\",9,\"Recetas sanas y buenas\")\n",
    "li.isbn = \"0-123456-78-9\"\n",
    "li.autor = \"Doña Juana\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Lista de productos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "productos = [ad, al]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "productos.append(li)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<__main__.Adorno at 0x14c58660940>,\n",
       " <__main__.Alimento at 0x14c586608d0>,\n",
       " <__main__.Libro at 0x14c58660978>]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "productos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lectura secuencial de productos con un for .. in"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2034\n",
      "NOMBRE\t\tVaso adornado\n",
      "PVP\t\t15\n",
      "DESCRIPCIÓN\tVaso de porcelana adornado con árboles \n",
      "\n",
      "REFERENCIA\t2035\n",
      "NOMBRE\t\tBotella de Aceite de Oliva Extra\n",
      "PVP\t\t5\n",
      "DESCRIPCIÓN\t250 ML\n",
      "PRODUCTOR\tLa Aceitera\n",
      "DISTRIBUIDOR\tDistribuciones SA \n",
      "\n",
      "REFERENCIA\t2036\n",
      "NOMBRE\t\tCocina Mediterránea\n",
      "PVP\t\t9\n",
      "DESCRIPCIÓN\tRecetas sanas y buenas\n",
      "ISBN\t\t0-123456-78-9\n",
      "AUTOR\t\tDoña Juana \n",
      "\n"
     ]
    }
   ],
   "source": [
    "for p in productos:\n",
    "    print(p,\"\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Podemos acceder a los atributos si son compartidos entre todos los objetos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2034 Vaso adornado\n",
      "2035 Botella de Aceite de Oliva Extra\n",
      "2036 Cocina Mediterránea\n"
     ]
    }
   ],
   "source": [
    "for p in productos:\n",
    "    print(p.referencia, p.nombre)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Pero si un objeto no tiene el atributo deseado, dará error:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'Adorno' object has no attribute 'autor'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-8-36e9baf5c1cc>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mp\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mproductos\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m     \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mautor\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'Adorno' object has no attribute 'autor'"
     ]
    }
   ],
   "source": [
    "for p in productos:\n",
    "    print(p.autor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Tendremos que tratar cada subclase de forma distinta, gracias a la función isistance():"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2034 Vaso adornado\n",
      "2035 Botella de Aceite de Oliva Extra La Aceitera\n",
      "2036 Cocina Mediterránea 0-123456-78-9\n"
     ]
    }
   ],
   "source": [
    "for p in productos:\n",
    "    if( isinstance(p, Adorno) ):\n",
    "        print(p.referencia,p.nombre)\n",
    "    elif( isinstance(p, Alimento) ):\n",
    "        print(p.referencia,p.nombre,p.productor)\n",
    "    elif( isinstance(p, Libro) ):\n",
    "        print(p.referencia,p.nombre,p.isbn)        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Funciones que reciben objetos de distintas clases\n",
    "### Los obetos se envían por referencia a las funciones\n",
    "Así que debemos tener en cuenta que cualquier cambio realizado dentro afectará al propio objeto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2038\n",
      "NOMBRE\t\tBotella de Aceite de Oliva Extra\n",
      "PVP\t\t4.5\n",
      "DESCRIPCIÓN\t250 ML\n",
      "PRODUCTOR\tLa Aceitera\n",
      "DISTRIBUIDOR\tDistribuciones SA\n"
     ]
    }
   ],
   "source": [
    "def rebajar_producto(p, rebaja):\n",
    "    \"\"\"Rebaja un producto en porcentaje de su precio\"\"\"\n",
    "    p.pvp = p.pvp - (p.pvp/100 * rebaja)\n",
    "\n",
    "rebajar_producto(al, 10)\n",
    "print(al_rebajado)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2035\n",
      "NOMBRE\t\tBotella de Aceite de Oliva Extra\n",
      "PVP\t\t4.5\n",
      "DESCRIPCIÓN\t250 ML\n",
      "PRODUCTOR\tLa Aceitera\n",
      "DISTRIBUIDOR\tDistribuciones SA\n"
     ]
    }
   ],
   "source": [
    "print(al)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Una copia de un objeto también hace referencia al objeto copiado (como un acceso directo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "copia_al = al"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "copia_al.referencia = 2038"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2038\n",
      "NOMBRE\t\tBotella de Aceite de Oliva Extra\n",
      "PVP\t\t4.5\n",
      "DESCRIPCIÓN\t250 ML\n",
      "PRODUCTOR\tLa Aceitera\n",
      "DISTRIBUIDOR\tDistribuciones SA\n"
     ]
    }
   ],
   "source": [
    "print(copia_al)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2038\n",
      "NOMBRE\t\tBotella de Aceite de Oliva Extra\n",
      "PVP\t\t4.5\n",
      "DESCRIPCIÓN\t250 ML\n",
      "PRODUCTOR\tLa Aceitera\n",
      "DISTRIBUIDOR\tDistribuciones SA\n"
     ]
    }
   ],
   "source": [
    "print(al)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Esto también sucede con los tipos compuestos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "l = [1,2,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "l2 = l[:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "l2.append(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Para crear una copia 100% nueva debemos utilizar el módulo copy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "copia_ad = copy.copy(ad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2034\n",
      "NOMBRE\t\tVaso adornado\n",
      "PVP\t\t15\n",
      "DESCRIPCIÓN\tVaso de porcelana adornado con árboles\n"
     ]
    }
   ],
   "source": [
    "print(copia_ad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "copia_ad.pvp = 25"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2034\n",
      "NOMBRE\t\tVaso adornado\n",
      "PVP\t\t25\n",
      "DESCRIPCIÓN\tVaso de porcelana adornado con árboles\n"
     ]
    }
   ],
   "source": [
    "print(copia_ad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "REFERENCIA\t2034\n",
      "NOMBRE\t\tVaso adornado\n",
      "PVP\t\t15\n",
      "DESCRIPCIÓN\tVaso de porcelana adornado con árboles\n"
     ]
    }
   ],
   "source": [
    "print(ad)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Polimorfismo\n",
    "Se refiere a una propiedad de la herencia por la que objetos de distintas subclases pueden responder a una misma acción."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def rebajar_producto(p, rebaja):\n",
    "    p.pvp = p.pvp - (p.pvp/100 * rebaja)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El método  **rebajar_producto() ** es capaz de tomar objetos de distintas subclases y manipular el atributo **pvp**.\n",
    "\n",
    "La acción de manipular el **pvp** funcionará siempre que los objetos tengan ése atributo, pero en el caso de no ser así, daría error.\n",
    "\n",
    "La polimorfia es implícita en Python en todos los objetos, ya que todos son hijos de una superclase común llamada **Object**."
   ]
  }
 ],
 "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.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
