SlideShare a Scribd company logo
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Tech Lead en Qnective AG
Encantador de serpientes desde v2.2
Trabajo en remoto desde 2016
Incapaz de soportarun invierno de
verdad desde2016
Apenas sé hablar español técnico
Gran amante de las listas
Como esta
Python
Venga!
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
p1 = Point(0, 0)
print(f'{p1}: x={p1.x}, y={p1.y}')
p2 = Point(x=0, y=0)
print(f'{p1} == {p2} -> {p1 == p2}’)
Point(x=0, y=0): x=0, y=0
Point(x=0, y=0) == Point(x=0, y=0) -> True
El dato estructurado
De tuplas a clases
Añadiendo funcionalidad a una clase
Dataclass
Casosmás simples
Comparabilidad
Hashabilidad
Campos
Valores por defecto
Herencia
__slots__
Funciones de apoyo
Proyectos de terceros
Alternativas
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
El dato estructurado
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
red = 255, 0, 0
orange = (255, 165, 0)
green = tuple(0, 255, 0)
>>> orange[0]
255
>>> r, g, b = orange
>>> g
165
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
red = list((255, 0, 0))
orange = [255, 165, 0]
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
red = dict(red=255, green=0, blue=0)
orange = {'red': 255,
'green': 165,
'blue': 0}
>>> orange[‘blue’]
0
( )
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from collections import namedtuple
Colour = namedtuple(
'Colour', 'red green blue')
red = Colour(255, 0, 0)
orange = Colour(red=255,
green=165,
blue=0)
>>> orange.red
255
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from typing import NamedTuple
class Colour(NamedTuple):
red: int
green: int
blue: int = 0 # default!
red = Colour(255, 0)
orange = Colour(red=255, green=165)
>>> red.red
255
>>> orange.blue
0
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from types import SimpleNamespace
red = SimpleNamespace(red=255, green=0, blue=0)
>>> red.red
255
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
class Colour:
def __init__(self, red, green, blue=0):
self.red = red
self.green = green
self.blue = blue
red = Colour(255, 0)
orange = Colour(red=255, green=165)
>>> red.red
255
>>> orange.blue
0
>>> print(red)
<__main__.Colour object at 0x0000019119B09358>
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __repr__(self):
return (
f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
>>> print(red)
Colour(red=255, green=0, blue=0)
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
class Colour:
def __init__(self, red, green, blue=0):
self.red = red
self.green = green
self.blue = blue
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
>>> red1 = Colour(255, 0, 0)
>>> red2 = Colour(255, 0, 0)
>>> red1 == red2
False
>>> red1 == red1
True
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __eq__(self, other):
if other.__class__ is not self.__class__:
return NotImplemented
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
>>> red1 = Colour(255, 0, 0)
>>> red2 = Colour(255, 0, 0)
>>> red1 == red2
True
>>> red1 is red2
False
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
class Colour:
def __init__(self, red, green, blue=0):
self.red = red
self.green = green
self.blue = blue
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
def __eq__(self, other):
if other.__class__ is not self.__class__:
return NotImplemented
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
>>> list(sorted([orange, red]))
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: '<' not supported between instances of
'Colour' and 'Colour'
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) < (
other.red, other.green, other.blue)
return NotImplemented
...
>>> list(sorted([orange, red]))
[Colour(red=255, green=0, blue=0), Colour(red=255,
green=165, blue=0)]
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
class Colour:
def __init__(self, red, green, blue=0):
self.red = red
self.green = green
self.blue = blue
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) >= (
other.red, other.green, other.blue)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) > (
other.red, other.green, other.blue)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) <= (
other.red, other.green, other.blue)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) < (
other.red, other.green, other.blue)
return NotImplemented
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __delattr__(self, name):
raise TypeError(f'cannot delete field {name}')
def __setattr__(self, name, value):
raise TypeError(f'cannot assign to field {name}’)
>>> red = Colour(255, 0, 0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 4, in __init__
File "<input>", line 48, in __setattr__
TypeError: cannot assign to field red
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __init__(self, red, green, blue=0):
object.__setattr__(self, "red", red)
object.__setattr__(self, "green", green)
object.__setattr__(self, "blue", blue)
>>> red = Colour(255, 0, 0)
>>> red.blue = 1
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 23, in __setattr__
TypeError: cannot assign to field blue
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def __hash__(self):
return hash((self.red, self.green, self.blue))
>>> hash(red)
1738572376461218158
>> set([red])
{Colour(red=255, green=0, blue=0)}
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
class Colour:
def __init__(self, red, green, blue=0):
object.__setattr__(self, "red", red)
object.__setattr__(self, "green", green)
object.__setattr__(self, "blue", blue)
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) >= (
other.red, other.green, other.blue)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) > (
other.red, other.green, other.blue)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) <= (
other.red, other.green, other.blue)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) < (
other.red, other.green, other.blue)
return NotImplemented
def __delattr__(self, name):
raise TypeError(f'cannot delete field {name}')
def __setattr__(self, name, value):
raise TypeError(f'cannot assign to field {name}')
def __hash__(self):
return hash((self.red, self.green, self.blue))
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Añade.
Otro.
Campo.
El módulo dataclasses
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass
@dataclass
class Colour:
red: int
green: int
blue: int
orange = Colour(red=255, green=165, blue=0)
red = Colour(255, 0, 0)
>>> red
Colour(red=255, green=0, blue=0)
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
# Python 3.5
from typing import Optional
def fun(width: float,
name: Optional[str]=None) -> None:
pass
# Python 3.6
temperature: float
temperature = 'cold'
class Measurement:
speed: float
__annotations__
from dataclasses import dataclass
@dataclass
class Colour:
red: int
green: int
blue: int
orange = Colour(red=255, green=165, blue=0)
red = Colour(255, 0, 0)
red2 = Colour(255, 0, 0)
>>> red == red2
True
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass
@dataclass
class Colour:
red: int
green: int
blue: int
red = Colour(255, 0, 0)
>>> red.red = 240
>>> red
Colour(red=240, green=0, blue=0)
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass
@dataclass
class Colour:
red: int
green: int
blue: int
>>> list(sorted([orange, red]))
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: '<' not supported between instances of
'Colour' and 'Colour'
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass(order=True)
class Colour:
red: int
green: int
blue: int
>>> list(sorted([orange, red]))
[Colour(red=255, green=0, blue=0),
Colour(red=255, green=165, blue=0)]
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def dataclass(_cls=None, *, order=False):
def wrap(cls):
return _process_class(cls, order)
# See if we're being called as @dataclass
# or @dataclass().
if _cls is None:
# We're called with parens.
return wrap
# We're called as @dataclass without parens.
return wrap(_cls)
@dataclass(order=True)
class Colour:
red: int
green: int
blue: int
>>> hash(red)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'Colour'
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass(order=True, frozen=True)
class Colour:
red: int
green: int
blue: int
>>> hash(red)
1738572376461218158
>> set([red])
{Colour(red=255, green=0, blue=0)}
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass(order=True, frozen=True)
class Colour:
red: int
green: int
blue: int
>>> red.red = 240
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign
to field 'red'
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Dataclass
@dataclass(order=True, frozen=True)
class Colour:
red: int
green: int
blue: int
Claseartesanal
• class Colour:
def __init__(self, red, green, blue=0):
object.__setattr__(self, "red", red)
object.__setattr__(self, "green", green)
object.__setattr__(self, "blue", blue)
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) >= (
other.red, other.green, other.blue)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) > (
other.red, other.green, other.blue)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) <= (
other.red, other.green, other.blue)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) < (
other.red, other.green, other.blue)
return NotImplemented
def __delattr__(self, name):
raise TypeError(f'cannot delete field {name}')
def __setattr__(self, name, value):
raise TypeError(f'cannot assign to field {name}')
def __hash__(self):
return hash((self.red, self.green, self.blue))
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
def dataclass(
_cls=None, *,
init=True,
repr=True,
eq=True,
order=False,
unsafe_hash=False,
frozen=False):
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Los campos de una dataclass
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass
class Colour:
red: int
green: int
blue: int = 0
orange = Colour(red=255, green=165)
red = Colour(255, 0)
>>> red
Colour(red=255, green=0, blue=0)
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from typing import List
@dataclass
class Employee:
name: str
surname: str
children: List[str] = []
john = Employee('John', 'Green')
hank = Employee('Hank', 'Green’)
john.children.append('Henry')
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Traceback (most recent call last):
File "<input>", line 3, in <module>
File "dataclasses.py", line 966, in dataclass
return wrap(_cls)
File "dataclasses.py", line 958, in wrap
return _process_class(cls, init, repr, eq, order,
unsafe_hash, frozen)
File "dataclasses.py", line 809, in _process_class
for name, type in cls_annotations.items()]
File "dataclasses.py", line 809, in <listcomp>
for name, type in cls_annotations.items()]
File "dataclasses.py", line 702, in _get_field
raise ValueError(f'mutable default
{type(f.default)} for field '
ValueError: mutable default <class 'list'> for field
children is not allowed: use default_factory
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass, field
from typing import List
@dataclass
class Employee:
name: str
surname: str
children: List[str] = field(default_factory=list)
john = Employee('John', 'Green')
hank = Employee('Hank', 'Green')
john.children.append('Henry')
john.children.append('Alice’)
>>> hank.children
[]
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
__annotations__
dataclasses.Field
__dataclass_fields__
def field(*,
default=MISSING,
default_factory=MISSING,
init=True,
repr=True,
hash=None,
compare=True,
metadata=None):
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from typing import ClassVar
@dataclass
class Colour:
MAX: ClassVar[int] = 255
red: int
green: int
blue: int = 0
red = Colour(255, 0)
orange = Colour(255, 165)
>>> red.MAX
255
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import dataclass, field, InitVar
@dataclass
class Address:
protocol: InitVar[str]
host: InitVar[str]
url: str = field(init=False)
def __post_init__(self, protocol, host):
self.url = f'{protocol}://{host}/'
addr = Address('http', ‘example.com’)
>>> addr
Address(url='http://google.com/')
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass
class Point1d:
x: float
@dataclass
class Point2d(Point1d):
y: float
@dataclass
class Point3d(Point2d):
z: float
p1 = Point1d(11.1)
p2 = Point2d(22.2, 33.3)
p3 = Point3d(44.4, 55.5, 66.6)
>>> p1, p2, p3
(Point1d(x=11.1), Point2d(x=22.2, y=33.3), Point3d(x=44.4, y=55.5,
z=66.6))
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
@dataclass
class Colour:
__slots__ = (
'red’,
'green’,
'blue')
red: int
green: int
blue: int
>>> red.check = True
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Colour' object has no attribute
'check'
Rapidez de acceso
Restricción de creación de campos
Ahorro de espacio
¡Sin valores por defecto!
Funciones de apoyo
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
fields Lista los campos guardados. Funciona con instancias y
clases.
asdict Convierte un objeto en diccionario de forma recursiva
astuple Convierte un objeto en tupla de forma recursiva
replace Crea una copia (no profunda) de un objeto con algunos
campos cambiados de valor.
is_dataclass Comprueba si un objeto o clase es una dataclass
make_dataclass Crea una nueva clase con dataclass
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
fields Lista los campos guardados. Funciona con instancias y
clases.
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
>>> dataclasses.fields(red)
(Field(name='red’,...
Field(name='green',type=<class
'int'>,default=<dataclasses._MISSING_TYPE object at
0x0000028B13380208>,default_factory=<dataclasses._MISSI
NG_TYPE object at
0x0000028B13380208>,init=True,repr=True,hash=None,compa
re=True,metadata=mappingproxy({}),_field_type=_FIELD),
Field(name='blue’,...))
asdict Convierte un objeto en diccionario de forma recursiva
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
>>> dataclasses.asdict(red)
{'red': 255, 'green': 0, 'blue': 0}
astuple Convierte un objeto en tupla de forma recursiva
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
>>> dataclasses.astuple(red)
(255, 0, 0)
replace Crea una copia (no profunda) de un objeto con algunos
campos cambiados de valor.
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
>>> red2 = dataclasses.replace(red, blue=12)
>>> red2
Colour(red=255, green=0, blue=12)
is_dataclass Comprueba si un objeto o clase es una dataclass
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
>>> dataclasses.is_dataclass(red)
True
>>> dataclasses.is_dataclass(Colour)
True
>>> dataclasses.is_dataclass([])
False
make_dataclass Crea una nueva clase con dataclass
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
from dataclasses import make_dataclass
Colour = make_dataclass('Colour',
fields=[('red', int), ('green', int),
('blue', int)])
red = Colour(255, 0, 0)
orange = Colour(255, 165, 0)
Proyectos relacionados
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
dataslots Decorador with_slots, añade slots a una
dataclass.
dataclass-factory Crea instancias de dataclasses a partir de
diccionarios. Inverso a asdict.
strictclasses Decorador que hace que se comprueben tipos
en asignación.
dataclassinspector Intenta mostrar el equivalente al código
generado por una dataclass. Intenta.
fistro Genera instancias de dataclasses con datos
para pruebas. Fixtures.
dataclasses-jsonschema Crea JSON schema a partir de una dataclass.
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
La alternativa
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
import attr
@attr.s
class Colour:
red: int = attr.ib()
green: int = attr.ib()
blue: int = attr.ib()
red = Colour(255, 0, 0)
>>> red
Colour(red=255, green=0, blue=0)
Funciona desde Python 2.7
Soporta __slots__
Validadores
Convertidores
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
La recta final
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
El dato estructurado
De tuplas a clases
Añadiendo funcionalidad a una clase
Dataclass
Casosmás simples
Comparabilidad
Hashabilidad
Campos
Valores por defecto
Herencia
__slots__
Funciones de apoyo
Proyectos de terceros
Alternativas
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Dataclass
@dataclass(order=True, frozen=True)
class Colour:
red: int
green: int
blue: int
Claseartesanal
• class Colour:
def __init__(self, red, green, blue=0):
object.__setattr__(self, "red", red)
object.__setattr__(self, "green", green)
object.__setattr__(self, "blue", blue)
def __repr__(self):
return (f"{self.__class__.__name__}("
f"red={self.red}, green={self.green}, "
f"blue={self.blue})")
def __eq__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) == (
other.red, other.green, other.blue)
return NotImplemented
def __ge__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) >= (
other.red, other.green, other.blue)
return NotImplemented
def __gt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) > (
other.red, other.green, other.blue)
return NotImplemented
def __le__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) <= (
other.red, other.green, other.blue)
return NotImplemented
def __lt__(self, other):
if other.__class__ is self.__class__:
return (self.red, self.green, self.blue) < (
other.red, other.green, other.blue)
return NotImplemented
def __delattr__(self, name):
raise TypeError(f'cannot delete field {name}')
def __setattr__(self, name, value):
raise TypeError(f'cannot assign to field {name}')
def __hash__(self):
return hash((self.red, self.green, self.blue))
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Añade.
Otro.
Campo.
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
Todd Ehlers en Flickr
Philippe_ en Flickr
Leo Hidalgo en Flickr
Antonio Trogu en Flickr
Bruce Baugh en Flickr
VivaAntarctica en Flickr
eightydaysjet en Flickr
Farrukh en Flickr
Andy Wilson en Flickr
Valerie Reneé en Flickr
Paul Keller en Flickr
Marc Wesel en Flickr
Matteo Tarenghi en Flickr
JD Hancock en Flickr
Smabs Sputzer (1956-2017) en Flickr
Loco Races en Flickr
Cameron Daigle en Flickr

More Related Content

What's hot

Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
Mauro Rocco
 
Neat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protectionNeat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protection
Mikhail Egorov
 
Take a load off! Load testing your Oracle APEX or JDeveloper web applications
Take a load off! Load testing your Oracle APEX or JDeveloper web applicationsTake a load off! Load testing your Oracle APEX or JDeveloper web applications
Take a load off! Load testing your Oracle APEX or JDeveloper web applications
Sage Computing Services
 
Node.js Express Framework
Node.js Express FrameworkNode.js Express Framework
Node.js Express Framework
TheCreativedev Blog
 
Microservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring CloudMicroservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring Cloud
Eberhard Wolff
 
JSON Array Indexes in MySQL
JSON Array Indexes in MySQLJSON Array Indexes in MySQL
JSON Array Indexes in MySQL
Norvald Ryeng
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
Cheng Ta Yeh
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Victor Rentea
 
容器化後,持續交付不可缺的敲門磚 - Helm
容器化後,持續交付不可缺的敲門磚 - Helm容器化後,持續交付不可缺的敲門磚 - Helm
容器化後,持續交付不可缺的敲門磚 - Helm
Hung-Yen Chen
 
Assessment methodology and approach
Assessment methodology and approachAssessment methodology and approach
Assessment methodology and approach
Blueinfy Solutions
 
Don't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using MocksDon't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using Mocks
Victor Rentea
 
JSON and the Oracle Database
JSON and the Oracle DatabaseJSON and the Oracle Database
JSON and the Oracle Database
Maria Colgan
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Philip Schwarz
 
The Rust Programming Language
The Rust Programming LanguageThe Rust Programming Language
The Rust Programming Language
Mario Alexandro Santini
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
Victor Rentea
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
Bryan Helmig
 
A5: Security Misconfiguration
A5: Security Misconfiguration A5: Security Misconfiguration
A5: Security Misconfiguration
Tariq Islam
 
Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 world
Yura Nosenko
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
Clean Code @Voxxed Days Cluj 2023 - opening KeynoteClean Code @Voxxed Days Cluj 2023 - opening Keynote
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
Victor Rentea
 

What's hot (20)

Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
 
Neat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protectionNeat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protection
 
Take a load off! Load testing your Oracle APEX or JDeveloper web applications
Take a load off! Load testing your Oracle APEX or JDeveloper web applicationsTake a load off! Load testing your Oracle APEX or JDeveloper web applications
Take a load off! Load testing your Oracle APEX or JDeveloper web applications
 
Node.js Express Framework
Node.js Express FrameworkNode.js Express Framework
Node.js Express Framework
 
Microservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring CloudMicroservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring Cloud
 
JSON Array Indexes in MySQL
JSON Array Indexes in MySQLJSON Array Indexes in MySQL
JSON Array Indexes in MySQL
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
 
容器化後,持續交付不可缺的敲門磚 - Helm
容器化後,持續交付不可缺的敲門磚 - Helm容器化後,持續交付不可缺的敲門磚 - Helm
容器化後,持續交付不可缺的敲門磚 - Helm
 
Assessment methodology and approach
Assessment methodology and approachAssessment methodology and approach
Assessment methodology and approach
 
Don't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using MocksDon't Be Mocked by your Mocks - Best Practices using Mocks
Don't Be Mocked by your Mocks - Best Practices using Mocks
 
JSON and the Oracle Database
JSON and the Oracle DatabaseJSON and the Oracle Database
JSON and the Oracle Database
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
The Rust Programming Language
The Rust Programming LanguageThe Rust Programming Language
The Rust Programming Language
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
 
A5: Security Misconfiguration
A5: Security Misconfiguration A5: Security Misconfiguration
A5: Security Misconfiguration
 
Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 world
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
 
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
Clean Code @Voxxed Days Cluj 2023 - opening KeynoteClean Code @Voxxed Days Cluj 2023 - opening Keynote
Clean Code @Voxxed Days Cluj 2023 - opening Keynote
 

Similar to Dataclasses en Python 3.7: Empieza a borrar código

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
Fwdays
 
DDDesign Challenges
DDDesign ChallengesDDDesign Challenges
DDDesign Challenges
Yves Reynhout
 
Haskell Tour (Part 3)
Haskell Tour (Part 3)Haskell Tour (Part 3)
Haskell Tour (Part 3)
William Taysom
 
Advanced python
Advanced pythonAdvanced python
Advanced python
EU Edge
 
Functional DDD
Functional DDDFunctional DDD
Functional DDD
Alessandro Melchiori
 
Eric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protectionEric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protection
GuardSquare
 
Jeop game-final-review
Jeop game-final-reviewJeop game-final-review
Jeop game-final-review
Stephanie Weirich
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
David Golden
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
Arturo Herrero
 
Madrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyMadrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovy
Iván López Martín
 

Similar to Dataclasses en Python 3.7: Empieza a borrar código (11)

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
DDDesign Challenges
DDDesign ChallengesDDDesign Challenges
DDDesign Challenges
 
Haskell Tour (Part 3)
Haskell Tour (Part 3)Haskell Tour (Part 3)
Haskell Tour (Part 3)
 
Advanced python
Advanced pythonAdvanced python
Advanced python
 
Functional DDD
Functional DDDFunctional DDD
Functional DDD
 
Eric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protectionEric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protection
 
Jeop game-final-review
Jeop game-final-reviewJeop game-final-review
Jeop game-final-review
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Madrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyMadrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovy
 

Recently uploaded

Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Envertis Software Solutions
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
lorraineandreiamcidl
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
Rakesh Kumar R
 
DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
Gerardo Pardo-Castellote
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
pavan998932
 

Recently uploaded (20)

Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise EditionWhy Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
Why Choose Odoo 17 Community & How it differs from Odoo 17 Enterprise Edition
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
 
DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
 

Dataclasses en Python 3.7: Empieza a borrar código

  • 1. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 2. Tech Lead en Qnective AG Encantador de serpientes desde v2.2 Trabajo en remoto desde 2016 Incapaz de soportarun invierno de verdad desde2016 Apenas sé hablar español técnico Gran amante de las listas Como esta Python Venga! Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 3. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from dataclasses import dataclass @dataclass class Point: x: int y: int p1 = Point(0, 0) print(f'{p1}: x={p1.x}, y={p1.y}') p2 = Point(x=0, y=0) print(f'{p1} == {p2} -> {p1 == p2}’) Point(x=0, y=0): x=0, y=0 Point(x=0, y=0) == Point(x=0, y=0) -> True
  • 4. El dato estructurado De tuplas a clases Añadiendo funcionalidad a una clase Dataclass Casosmás simples Comparabilidad Hashabilidad Campos Valores por defecto Herencia __slots__ Funciones de apoyo Proyectos de terceros Alternativas Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 5. El dato estructurado Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 6. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 red = 255, 0, 0 orange = (255, 165, 0) green = tuple(0, 255, 0) >>> orange[0] 255 >>> r, g, b = orange >>> g 165
  • 7. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 red = list((255, 0, 0)) orange = [255, 165, 0]
  • 8. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 red = dict(red=255, green=0, blue=0) orange = {'red': 255, 'green': 165, 'blue': 0} >>> orange[‘blue’] 0
  • 9. ( ) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from collections import namedtuple Colour = namedtuple( 'Colour', 'red green blue') red = Colour(255, 0, 0) orange = Colour(red=255, green=165, blue=0) >>> orange.red 255
  • 10. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from typing import NamedTuple class Colour(NamedTuple): red: int green: int blue: int = 0 # default! red = Colour(255, 0) orange = Colour(red=255, green=165) >>> red.red 255 >>> orange.blue 0
  • 11. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from types import SimpleNamespace red = SimpleNamespace(red=255, green=0, blue=0) >>> red.red 255
  • 12. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 class Colour: def __init__(self, red, green, blue=0): self.red = red self.green = green self.blue = blue red = Colour(255, 0) orange = Colour(red=255, green=165) >>> red.red 255 >>> orange.blue 0
  • 13. >>> print(red) <__main__.Colour object at 0x0000019119B09358> Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 14. def __repr__(self): return ( f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") >>> print(red) Colour(red=255, green=0, blue=0) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 15. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 class Colour: def __init__(self, red, green, blue=0): self.red = red self.green = green self.blue = blue def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})")
  • 16. >>> red1 = Colour(255, 0, 0) >>> red2 = Colour(255, 0, 0) >>> red1 == red2 False >>> red1 == red1 True Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 17. def __eq__(self, other): if other.__class__ is not self.__class__: return NotImplemented return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue) >>> red1 = Colour(255, 0, 0) >>> red2 = Colour(255, 0, 0) >>> red1 == red2 True >>> red1 is red2 False Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 18. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 class Colour: def __init__(self, red, green, blue=0): self.red = red self.green = green self.blue = blue def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") def __eq__(self, other): if other.__class__ is not self.__class__: return NotImplemented return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue)
  • 19. >>> list(sorted([orange, red])) Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: '<' not supported between instances of 'Colour' and 'Colour' Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 20. def __lt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) < ( other.red, other.green, other.blue) return NotImplemented ... >>> list(sorted([orange, red])) [Colour(red=255, green=0, blue=0), Colour(red=255, green=165, blue=0)] Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 21. class Colour: def __init__(self, red, green, blue=0): self.red = red self.green = green self.blue = blue def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") def __eq__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue) return NotImplemented def __ge__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) >= ( other.red, other.green, other.blue) return NotImplemented def __gt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) > ( other.red, other.green, other.blue) return NotImplemented def __le__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) <= ( other.red, other.green, other.blue) return NotImplemented def __lt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) < ( other.red, other.green, other.blue) return NotImplemented Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 22. def __delattr__(self, name): raise TypeError(f'cannot delete field {name}') def __setattr__(self, name, value): raise TypeError(f'cannot assign to field {name}’) >>> red = Colour(255, 0, 0) Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 4, in __init__ File "<input>", line 48, in __setattr__ TypeError: cannot assign to field red Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 23. def __init__(self, red, green, blue=0): object.__setattr__(self, "red", red) object.__setattr__(self, "green", green) object.__setattr__(self, "blue", blue) >>> red = Colour(255, 0, 0) >>> red.blue = 1 Traceback (most recent call last): File "<input>", line 1, in <module> File "<input>", line 23, in __setattr__ TypeError: cannot assign to field blue Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 24. def __hash__(self): return hash((self.red, self.green, self.blue)) >>> hash(red) 1738572376461218158 >> set([red]) {Colour(red=255, green=0, blue=0)} Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 25. class Colour: def __init__(self, red, green, blue=0): object.__setattr__(self, "red", red) object.__setattr__(self, "green", green) object.__setattr__(self, "blue", blue) def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") def __eq__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue) return NotImplemented def __ge__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) >= ( other.red, other.green, other.blue) return NotImplemented def __gt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) > ( other.red, other.green, other.blue) return NotImplemented def __le__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) <= ( other.red, other.green, other.blue) return NotImplemented def __lt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) < ( other.red, other.green, other.blue) return NotImplemented def __delattr__(self, name): raise TypeError(f'cannot delete field {name}') def __setattr__(self, name, value): raise TypeError(f'cannot assign to field {name}') def __hash__(self): return hash((self.red, self.green, self.blue)) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 26. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 Añade. Otro. Campo.
  • 27. El módulo dataclasses Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 28. from dataclasses import dataclass @dataclass class Colour: red: int green: int blue: int orange = Colour(red=255, green=165, blue=0) red = Colour(255, 0, 0) >>> red Colour(red=255, green=0, blue=0) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 29. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 # Python 3.5 from typing import Optional def fun(width: float, name: Optional[str]=None) -> None: pass # Python 3.6 temperature: float temperature = 'cold' class Measurement: speed: float __annotations__
  • 30. from dataclasses import dataclass @dataclass class Colour: red: int green: int blue: int orange = Colour(red=255, green=165, blue=0) red = Colour(255, 0, 0) red2 = Colour(255, 0, 0) >>> red == red2 True Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 31. from dataclasses import dataclass @dataclass class Colour: red: int green: int blue: int red = Colour(255, 0, 0) >>> red.red = 240 >>> red Colour(red=240, green=0, blue=0) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 32. from dataclasses import dataclass @dataclass class Colour: red: int green: int blue: int >>> list(sorted([orange, red])) Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: '<' not supported between instances of 'Colour' and 'Colour' Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 33. @dataclass(order=True) class Colour: red: int green: int blue: int >>> list(sorted([orange, red])) [Colour(red=255, green=0, blue=0), Colour(red=255, green=165, blue=0)] Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 34. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 def dataclass(_cls=None, *, order=False): def wrap(cls): return _process_class(cls, order) # See if we're being called as @dataclass # or @dataclass(). if _cls is None: # We're called with parens. return wrap # We're called as @dataclass without parens. return wrap(_cls)
  • 35. @dataclass(order=True) class Colour: red: int green: int blue: int >>> hash(red) Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: unhashable type: 'Colour' Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 36. @dataclass(order=True, frozen=True) class Colour: red: int green: int blue: int >>> hash(red) 1738572376461218158 >> set([red]) {Colour(red=255, green=0, blue=0)} Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 37. @dataclass(order=True, frozen=True) class Colour: red: int green: int blue: int >>> red.red = 240 Traceback (most recent call last): File "<input>", line 1, in <module> File "<string>", line 3, in __setattr__ dataclasses.FrozenInstanceError: cannot assign to field 'red' Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 38. Dataclass @dataclass(order=True, frozen=True) class Colour: red: int green: int blue: int Claseartesanal • class Colour: def __init__(self, red, green, blue=0): object.__setattr__(self, "red", red) object.__setattr__(self, "green", green) object.__setattr__(self, "blue", blue) def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") def __eq__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue) return NotImplemented def __ge__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) >= ( other.red, other.green, other.blue) return NotImplemented def __gt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) > ( other.red, other.green, other.blue) return NotImplemented def __le__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) <= ( other.red, other.green, other.blue) return NotImplemented def __lt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) < ( other.red, other.green, other.blue) return NotImplemented def __delattr__(self, name): raise TypeError(f'cannot delete field {name}') def __setattr__(self, name, value): raise TypeError(f'cannot assign to field {name}') def __hash__(self): return hash((self.red, self.green, self.blue)) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 40. Los campos de una dataclass Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 41. @dataclass class Colour: red: int green: int blue: int = 0 orange = Colour(red=255, green=165) red = Colour(255, 0) >>> red Colour(red=255, green=0, blue=0) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 42. from typing import List @dataclass class Employee: name: str surname: str children: List[str] = [] john = Employee('John', 'Green') hank = Employee('Hank', 'Green’) john.children.append('Henry') Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 43. Traceback (most recent call last): File "<input>", line 3, in <module> File "dataclasses.py", line 966, in dataclass return wrap(_cls) File "dataclasses.py", line 958, in wrap return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen) File "dataclasses.py", line 809, in _process_class for name, type in cls_annotations.items()] File "dataclasses.py", line 809, in <listcomp> for name, type in cls_annotations.items()] File "dataclasses.py", line 702, in _get_field raise ValueError(f'mutable default {type(f.default)} for field ' ValueError: mutable default <class 'list'> for field children is not allowed: use default_factory Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 44. from dataclasses import dataclass, field from typing import List @dataclass class Employee: name: str surname: str children: List[str] = field(default_factory=list) john = Employee('John', 'Green') hank = Employee('Hank', 'Green') john.children.append('Henry') john.children.append('Alice’) >>> hank.children [] Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 45. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 __annotations__ dataclasses.Field __dataclass_fields__
  • 47. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from typing import ClassVar @dataclass class Colour: MAX: ClassVar[int] = 255 red: int green: int blue: int = 0 red = Colour(255, 0) orange = Colour(255, 165) >>> red.MAX 255
  • 48. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from dataclasses import dataclass, field, InitVar @dataclass class Address: protocol: InitVar[str] host: InitVar[str] url: str = field(init=False) def __post_init__(self, protocol, host): self.url = f'{protocol}://{host}/' addr = Address('http', ‘example.com’) >>> addr Address(url='http://google.com/')
  • 49. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 @dataclass class Point1d: x: float @dataclass class Point2d(Point1d): y: float @dataclass class Point3d(Point2d): z: float p1 = Point1d(11.1) p2 = Point2d(22.2, 33.3) p3 = Point3d(44.4, 55.5, 66.6) >>> p1, p2, p3 (Point1d(x=11.1), Point2d(x=22.2, y=33.3), Point3d(x=44.4, y=55.5, z=66.6))
  • 50. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 @dataclass class Colour: __slots__ = ( 'red’, 'green’, 'blue') red: int green: int blue: int >>> red.check = True Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'Colour' object has no attribute 'check' Rapidez de acceso Restricción de creación de campos Ahorro de espacio ¡Sin valores por defecto!
  • 51. Funciones de apoyo Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 52. fields Lista los campos guardados. Funciona con instancias y clases. asdict Convierte un objeto en diccionario de forma recursiva astuple Convierte un objeto en tupla de forma recursiva replace Crea una copia (no profunda) de un objeto con algunos campos cambiados de valor. is_dataclass Comprueba si un objeto o clase es una dataclass make_dataclass Crea una nueva clase con dataclass Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 53. fields Lista los campos guardados. Funciona con instancias y clases. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 >>> dataclasses.fields(red) (Field(name='red’,... Field(name='green',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x0000028B13380208>,default_factory=<dataclasses._MISSI NG_TYPE object at 0x0000028B13380208>,init=True,repr=True,hash=None,compa re=True,metadata=mappingproxy({}),_field_type=_FIELD), Field(name='blue’,...))
  • 54. asdict Convierte un objeto en diccionario de forma recursiva Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 >>> dataclasses.asdict(red) {'red': 255, 'green': 0, 'blue': 0}
  • 55. astuple Convierte un objeto en tupla de forma recursiva Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 >>> dataclasses.astuple(red) (255, 0, 0)
  • 56. replace Crea una copia (no profunda) de un objeto con algunos campos cambiados de valor. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 >>> red2 = dataclasses.replace(red, blue=12) >>> red2 Colour(red=255, green=0, blue=12)
  • 57. is_dataclass Comprueba si un objeto o clase es una dataclass Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 >>> dataclasses.is_dataclass(red) True >>> dataclasses.is_dataclass(Colour) True >>> dataclasses.is_dataclass([]) False
  • 58. make_dataclass Crea una nueva clase con dataclass Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 from dataclasses import make_dataclass Colour = make_dataclass('Colour', fields=[('red', int), ('green', int), ('blue', int)]) red = Colour(255, 0, 0) orange = Colour(255, 165, 0)
  • 59. Proyectos relacionados Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 60. dataslots Decorador with_slots, añade slots a una dataclass. dataclass-factory Crea instancias de dataclasses a partir de diccionarios. Inverso a asdict. strictclasses Decorador que hace que se comprueben tipos en asignación. dataclassinspector Intenta mostrar el equivalente al código generado por una dataclass. Intenta. fistro Genera instancias de dataclasses con datos para pruebas. Fixtures. dataclasses-jsonschema Crea JSON schema a partir de una dataclass. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 61. La alternativa Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 62. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 import attr @attr.s class Colour: red: int = attr.ib() green: int = attr.ib() blue: int = attr.ib() red = Colour(255, 0, 0) >>> red Colour(red=255, green=0, blue=0)
  • 63. Funciona desde Python 2.7 Soporta __slots__ Validadores Convertidores Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 64. La recta final Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 65. El dato estructurado De tuplas a clases Añadiendo funcionalidad a una clase Dataclass Casosmás simples Comparabilidad Hashabilidad Campos Valores por defecto Herencia __slots__ Funciones de apoyo Proyectos de terceros Alternativas Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 66. Dataclass @dataclass(order=True, frozen=True) class Colour: red: int green: int blue: int Claseartesanal • class Colour: def __init__(self, red, green, blue=0): object.__setattr__(self, "red", red) object.__setattr__(self, "green", green) object.__setattr__(self, "blue", blue) def __repr__(self): return (f"{self.__class__.__name__}(" f"red={self.red}, green={self.green}, " f"blue={self.blue})") def __eq__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) == ( other.red, other.green, other.blue) return NotImplemented def __ge__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) >= ( other.red, other.green, other.blue) return NotImplemented def __gt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) > ( other.red, other.green, other.blue) return NotImplemented def __le__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) <= ( other.red, other.green, other.blue) return NotImplemented def __lt__(self, other): if other.__class__ is self.__class__: return (self.red, self.green, self.blue) < ( other.red, other.green, other.blue) return NotImplemented def __delattr__(self, name): raise TypeError(f'cannot delete field {name}') def __setattr__(self, name, value): raise TypeError(f'cannot assign to field {name}') def __hash__(self): return hash((self.red, self.green, self.blue)) Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 67. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 Añade. Otro. Campo.
  • 68. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018
  • 69. Jacobo de Vera | @jovianjake | PyDay Tenerife 2018 Todd Ehlers en Flickr Philippe_ en Flickr Leo Hidalgo en Flickr Antonio Trogu en Flickr Bruce Baugh en Flickr VivaAntarctica en Flickr eightydaysjet en Flickr Farrukh en Flickr Andy Wilson en Flickr Valerie Reneé en Flickr Paul Keller en Flickr Marc Wesel en Flickr Matteo Tarenghi en Flickr JD Hancock en Flickr Smabs Sputzer (1956-2017) en Flickr Loco Races en Flickr Cameron Daigle en Flickr