Created
July 14, 2018 15:35
-
-
Save scardine/5163cd8c675e05d06dbb7a75082e2b8c to your computer and use it in GitHub Desktop.
Jupyter Notebook for my talk at JustPython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Novidades do Python 3.7" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import sys\n", | |
"sys.version" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## [PEP 557](https://www.python.org/dev/peps/pep-0557/): Data Classes\n", | |
"\n", | |
"Você gosta dos objetos de JavaScript?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p = {x: 1, y: 2}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p.x" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p.y" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Em Python é mais chato:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p = {\"x\": 1, \"y\": 2}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p.x" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"p[\"x\"]" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Para fazer algo mais parecido com os objetos de JavaScript em Python:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Point(object):\n", | |
" def __init__(self, x, y):\n", | |
" self.x = x\n", | |
" self.y = y\n", | |
" \n", | |
"point = Point(1, 2)\n", | |
"point" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"A representação default é bem feia... Pra melhorar um pouco tem que implementar o método `__repr__`" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Point(object):\n", | |
" def __init__(self, x, y):\n", | |
" self.x = x\n", | |
" self.y = y\n", | |
" def __repr__(self):\n", | |
" return f\"Point(x={self.x}, y={self.y})\"\n", | |
" \n", | |
"point = Point(1, 2)\n", | |
"point" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Melhorou um pouco. Vamos testar o operador lógico de igualdade:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"point_a = Point(1, 2)\n", | |
"point_b = Point(1, 2)\n", | |
"point_a == point_b" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Novamente precisamos implementar outro magic method (`__eq__`) pra fazer funcionar:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Point(object):\n", | |
" def __init__(self, x, y):\n", | |
" self.x = x\n", | |
" self.y = y\n", | |
" def __repr__(self):\n", | |
" return f\"Point(x={self.x}, y={self.y})\"\n", | |
" def __eq__(self, other):\n", | |
" return self.x == other.x and self.y == other.y\n", | |
" \n", | |
"point_a = Point(1, 2)\n", | |
"point_b = Point(1, 2)\n", | |
"point_a == point_b" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Vamos fazer um dicionário de pontos:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"{point_a: 1, point_b: 2}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from hashlib import sha256\n", | |
"\n", | |
"class Point(object):\n", | |
" def __init__(self, x, y):\n", | |
" self.x = x\n", | |
" self.y = y\n", | |
" def __repr__(self):\n", | |
" return f\"Point(x={self.x}, y={self.y})\"\n", | |
" def __eq__(self, other):\n", | |
" return self.x == other.x and self.y == other.y\n", | |
" def __hash__(self):\n", | |
" return int(sha256(f\"{self.x},{self.y}\".encode('ascii')).hexdigest(), 16)\n", | |
" \n", | |
"point_a = Point(1, 2)\n", | |
"point_b = Point(2, 1)\n", | |
"\n", | |
"{point_a: 1, point_b: 2}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from collections import namedtuple\n", | |
"\n", | |
"Point = namedtuple('Point', ['x', 'y'])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"point_a = Point(1, 2)\n", | |
"point_b = Point(1, 2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# representação\n", | |
"point_a, point_b" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# igualdade\n", | |
"point_a == point_b" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# identidade\n", | |
"{point_a: 1, point_b: 2}" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Parece que tudo funciona! Será?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Point3D(Point):\n", | |
" def __init__(self, x, y, z):\n", | |
" super().__init__(x, y)\n", | |
" self.z = z\n", | |
" def __repr__(self):\n", | |
" return f\"Point(x={self.x}, y={self.y}, z={self.z})\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Point3D(1, 2, 3)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Entram as Data Classes:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from dataclasses import dataclass\n", | |
"\n", | |
"@dataclass\n", | |
"class Point(object):\n", | |
" x: int\n", | |
" y: int" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@dataclass\n", | |
"class Point3D(Point):\n", | |
" z: int" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## [PEP 562](http://www.python.org/dev/peps/pep-0562): Module Attributes Dinâmicos" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Todo mundo sabe que podemos implementar atributos dinâmicos implementando `__getattr__`:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"class Foo(object):\n", | |
" def __getattr__(self, name):\n", | |
" return f\"{name.title()} de Foo é Fola.\"\n", | |
" \n", | |
"f = Foo()\n", | |
"\n", | |
"f.bar" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Agora podemos fazer a mesma coisa ao nível de módulos:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# lib.py\n", | |
"\n", | |
"from warnings import warn\n", | |
"\n", | |
"deprecated_names = [\"funcao_antiga\", ...]\n", | |
"\n", | |
"def _funcao_antiga_obsoleta(arg, other):\n", | |
" ...\n", | |
"\n", | |
"def __getattr__(name):\n", | |
" if name in deprecated_names:\n", | |
" warn(f\"{name} está obsoleta\", DeprecationWarning)\n", | |
" return globals()[f\"{name}_obsoleta\"]\n", | |
" raise AttributeError(f\"module {__name__} não possui um atributo {name}\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## [PEP 553](http://www.python.org/dev/peps/pep-0553): Built-in breakpoint()\n", | |
"\n", | |
"Já usou o debugger do Python?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def divide(a, b):\n", | |
" breakpoint()\n", | |
" return a / b" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"divide(1, 0)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import os\n", | |
"os.environ['PYTHONBREAKPOINT'] = \"pdb\"" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## [PEP 560](http://www.python.org/dev/peps/pep-0560) e [PEP 563](http://www.python.org/dev/peps/pep-0563): Melhorias nas Anotações de Tipo" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# import annotations\n", | |
"\n", | |
"class Point:\n", | |
"\n", | |
" def __init__(self, x: int, y: int):\n", | |
" self.x = x\n", | |
" self.y = y\n", | |
"\n", | |
" def __add__(self, other: Point) -> Point:\n", | |
" return Point(self.x + other.x, self.y + other.y)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Outras Novidades\n", | |
"\n", | |
"Otimizações:\n", | |
"\n", | |
"* redução do overhead na chamada de muitos métodos da biblioteca padrão.\n", | |
"* chamadas de método estão 20% mais rápidas no geral!\n", | |
"* o tempo de espera na inicialização do Python foi reduzido entre 10 e 30%.\n", | |
"* o módulo typing está 7 vezes mais rápido.\n", | |
"\n", | |
"Miscelanea:\n", | |
"\n", | |
"* o módulo time novas funções de maior precisão descritas na [PEP 564](http://www.python.org/dev/peps/pep-0564).\n", | |
"* a nova implementação dos dicts na versão 3.6 passou a preservar a ordem de inserção (antes disso a ordem das chaves era aleatória) mas na versão 3.7 a preservação da ordem de inserção das chaves passou a ser uma garantida na especificação da linguagem.\n", | |
"* “async” and “await” passaram a ser palavras reservadas (keywords) e o módulo asyncio ganhou um face lift razoável, incluindo o suporte para context variables (veja abaixo) e melhorias na performance. Incluindo o novo asyncio.run() que dispensa a criação explícita de um event loop.\n", | |
"* se você usa threads concorrentes, o Python 3.7 traz o suporte para variáveis de contexto (parecido com Thread-Local Storage).\n", | |
"* o novo módulo importlib.resources da biblioteca padrão facilita o empacotamento de uma aplicação Python dispensando que você mantenha o caminho para recursos do programa dinamicamente.\n", | |
"* novas flags-X interessantes nas opções de linha de comando do interpretador Python, em expecial a -X importtime que mostra quanto tempo a aplicação está demorando nos imports.\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.0b1" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment