¿Cómo funcionan los Widgets de Jupyter?¶
¿Qué es un Widget?¶
¿Cómo funciona un ipywidget?¶
¿Qué tengo que tener en cuenta al implementar uno?¶
¿Qué es un Widget?¶
Y por qué deberían interesarme los widgets?¶
Advertencia!!!¶
¿Cómo funciona un ipywidget?¶
In [1]:
class Cosito:
def __init__(self, nombre):
self.nombre = nombre
ruflete = Cosito('ruflete')
print(ruflete)
<__main__.Cosito object at 0x000002664553B920>
In [2]:
class Cosito:
def __init__(self, nombre):
self.nombre = nombre
def __str__(self):
return self.nombre
def __repr__(self):
return f'Cosito("{self.nombre}")'
ruflete = Cosito('ruflete')
print('Esto es str:', ruflete)
print('Esto es repr:',repr(ruflete))
Esto es str: ruflete Esto es repr: Cosito("ruflete")
In [3]:
class Cosito:
html_template = '<i class="fa fa-hand-spock-o" style="font-size:48px;color:red">{nombre}</i>'
def __init__(self, nombre):
self.nombre = nombre
def __str__(self):
return self.nombre
def __repr__(self):
return f'Cosito("{self.nombre}")'
def _repr_html_(self):
return self.html_template.format(nombre=self.nombre)
ruflete = Cosito('ruflete')
print('Esto es str:', ruflete)
print('Esto es repr:',repr(ruflete))
ruflete
Esto es str: ruflete Esto es repr: Cosito("ruflete")
Out[3]:
ruflete
In [4]:
from ipywidgets import HTML, VBox, Image, IntSlider, link
from IPython.display import display
In [5]:
class Cosito:
html_template = '<i class="fa fa-hand-spock-o" style="font-size:48px;color:red">{nombre}</i>'
def __init__(self, nombre):
self.nombre = nombre
def __str__(self):
return self.nombre
def __repr__(self):
return f'Cosito("{self.nombre}")'
def _ipython_display_(self):
html = HTML(self.html_template.format(nombre=self.nombre))
with open('imagenes/ruflete.jpg','rb') as img:
imagen_data = img.read()
slider = IntSlider(min=100,max=300)
imagen = Image(value=imagen_data,height=200,width=300)
link((imagen,'width'),(slider,'value'))
display(VBox([html,imagen,slider]))
In [6]:
ruflete = Cosito('ruflete')
print('Esto es str:', ruflete)
print('Esto es repr:',repr(ruflete))
ruflete
Esto es str: ruflete Esto es repr: Cosito("ruflete")
VBox(children=(HTML(value='<i class="fa fa-hand-spock-o" style="font-size:48px;color:red">ruflete</i>'), Image…
In [7]:
from traitlets import Unicode, Int
from ipywidgets import Widget
class Cosito(Widget):
nombre = Unicode('cosito').tag(sync=True)
tamanio = Int(15).tag(sync=True, metadata={'marca':'tres chanchitos'})
ruflete = Cosito()
ruflete
Out[7]:
Cosito()
In [8]:
def llamado(cambio):
print('Ring ring!')
ruflete.observe(llamado)
ruflete.nombre = 'ruflete'
Ring ring!
Estructura del evento¶
def llamado(cambio):
print(cambio)
cambio = { 'owner' : Cosito(name='ruflete'), #'la instancia de un objeto HasTraits (traitlets)'
'old' : 'cosito', # valor viejo del atributo modificado
'new' : 'ruflete',# valor nuevo del atributo modificado
'name' : 'nombre' # nombre del atributo que fue modificado'
'type' : 'change' # tipo del evento observado
}
In [9]:
rosca = Cosito(nombre='rosca')
def hace_esto(cambio):
rosca.tamanio -= cambio['new']
ruflete.observe(hace_esto,names='tamanio')
In [10]:
def intentar_encastrar(cambio):
raise ValueError('No deberías hacer eso')
ruflete.observe(intentar_encastrar)
ruflete.tamanio = 0
ruflete
Ring ring!
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[10], line 5 2 raise ValueError('No deberías hacer eso') 4 ruflete.observe(intentar_encastrar) ----> 5 ruflete.tamanio = 0 6 ruflete File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\traitlets\traitlets.py:716, in TraitType.__set__(self, obj, value) 714 if self.read_only: 715 raise TraitError('The "%s" trait is read-only.' % self.name) --> 716 self.set(obj, value) File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\traitlets\traitlets.py:706, in TraitType.set(self, obj, value) 702 silent = False 703 if silent is not True: 704 # we explicitly compare silent to True just in case the equality 705 # comparison above returns something other than True/False --> 706 obj._notify_trait(self.name, old_value, new_value) File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\traitlets\traitlets.py:1513, in HasTraits._notify_trait(self, name, old_value, new_value) 1512 def _notify_trait(self, name: str, old_value: t.Any, new_value: t.Any) -> None: -> 1513 self.notify_change( 1514 Bunch( 1515 name=name, 1516 old=old_value, 1517 new=new_value, 1518 owner=self, 1519 type="change", 1520 ) 1521 ) File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\ipywidgets\widgets\widget.py:701, in Widget.notify_change(self, change) 698 if name in self.keys and self._should_send_property(name, getattr(self, name)): 699 # Send new state to front-end 700 self.send_state(key=name) --> 701 super().notify_change(change) File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\traitlets\traitlets.py:1525, in HasTraits.notify_change(self, change) 1523 def notify_change(self, change: Bunch) -> None: 1524 """Notify observers of a change event""" -> 1525 return self._notify_observers(change) File ~\dev\gh\akielbowicz\presentations\.venv\Lib\site-packages\traitlets\traitlets.py:1568, in HasTraits._notify_observers(self, event) 1565 elif isinstance(c, EventHandler) and c.name is not None: 1566 c = getattr(self, c.name) -> 1568 c(event) Cell In[10], line 2, in intentar_encastrar(cambio) 1 def intentar_encastrar(cambio): ----> 2 raise ValueError('No deberías hacer eso') ValueError: No deberías hacer eso
In [11]:
from ipywidgets import Output
output = Output(layout={'border': '1px solid black'})
@output.capture()
def intentar_encastrar_otra_vez(cambio):
raise ValueError('No deberías hacer eso otra vez')
ruflete.observe(intentar_encastrar_otra_vez)
output
Out[11]:
Output(layout=Layout(border_bottom='1px solid black', border_left='1px solid black', border_right='1px solid b…
In [12]:
from traitlets import Unicode, Bool, validate, TraitError
from ipywidgets import DOMWidget, register
@register
class Cosito(DOMWidget):
_view_name = Unicode('CositoView').tag(sync=True)
_view_module = Unicode('cosito_widget').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
var CositoModel = widgets.DOMWidgetModel.extend({
defaults : function() { ... };
});
var CositoView = widgets.DOMWidgetView.extend({
render : function() {
this.el.appendChild(this.input);
this.model.on('change:value',this.value_changed,this);
};
});
this.model.on('change:value',this.value_changed,this);
this.listenTo(this.model,'change:value',this.value_changed);
class Reloj(DOMWidget):
value = Date(None, allow_none=True).tag(sync=True, **date_serialization)
Traittypes¶
Serializador de numpy y pandas¶
Cuando empezamos a tener varios widgets que interactuan¶
In [13]:
from ipywidgets import FloatSlider, Dropdown
cosito = Cosito()
precio = FloatSlider(min=0,max=200)
etiqueta = Dropdown(options=['Nuevo','Usado','Reparado'])
def cambiar_precio(cambio):
cosito.precio = cambio['new']
def actualizacion_de_estado(cambio):
if cambio['new'] == 'Usado':
cosito.precio *= 0.45
cosito.etiqueta = cambio['new']
precio.observe(cambiar_precio)
etiqueta.observe(actualizacion_de_estado,names='value')
Ipywidgets Issue 2296¶
In [14]:
from traitlets import HasTraits, Float, observe, Unicode
class CositoModelo(HasTraits):
tamanio = Float()
nombre = Unicode()
precio = Float()
etiqueta = Unicode()
def recalcular_precio(self):
pass
@observe('tamanio')
def llamado(self, cambio):
pass
def __repr__(self):
pass
In [15]:
import ipywidgets as widgets
from traitlets import link
from IPython.display import display
class CositoVista:
def __init__(self, modelo):
self.model = modelo
self.tipo = widgets.Dropdown(options=["plastico", "metal"])
self.etiqueta = widgets.Label('Original')
self.tamanio = widgets.IntSlider()
self.precio = widgets.FloatLogSlider()
self.ipyview = widgets.HBox([widgets.VBox([self.tipo, ]),
widgets.VBox([self.etiqueta,
widgets.HBox([self.precio, self.tamanio])])])
link((modelo, 'tipo'), (self.tipo, 'value'))
link((modelo, 'etiqueta'), (self.etiqueta, 'value'))
link((modelo, 'precio'), (self.precio, 'value'))
link((modelo, 'tamanio'), (self.tamanio, 'value'))
def _ipython_display_(self):
display(self.ipyview)