├── .github └── workflows │ ├── forty-features.yml │ └── python-classes.yml ├── .gitmodules ├── [2013] Forty Features of Python that You May Not Know ├── Makefile ├── README.md ├── cover.tex ├── features │ ├── 01.tex │ ├── 02.tex │ ├── 03.tex │ ├── 04.tex │ ├── 05.tex │ ├── 06.tex │ ├── 07.tex │ ├── 08.tex │ ├── 09.tex │ ├── 10.tex │ ├── 11.tex │ ├── 12.tex │ ├── 13.tex │ ├── 14.tex │ ├── 15.tex │ ├── 16.tex │ ├── 17.tex │ ├── 18.tex │ ├── 19.tex │ ├── 20.tex │ ├── 21.tex │ ├── 22.tex │ ├── 23.tex │ ├── 24.tex │ ├── 25.tex │ ├── 26.tex │ ├── 27.tex │ ├── 28.tex │ ├── 29.tex │ ├── 30.tex │ ├── 31.tex │ ├── 32.tex │ ├── 33.tex │ ├── 34.tex │ ├── 35.tex │ ├── 36.tex │ ├── 37.tex │ ├── 38.tex │ ├── 39.tex │ └── 40.tex ├── forty-features.tex ├── intro.tex └── pics │ ├── CREDITS │ ├── a-clockwork-orange-2.jpg │ ├── a-clockwork-orange.jpg │ ├── cover.svg │ ├── first-day-internet.jpg │ ├── omg-face.jpg │ ├── shaolin.jpg │ ├── trollface.png │ ├── un-palo.jpg │ └── xkcd-353.png ├── [2014] Classes in Python: You're Doing it Wrong ├── Makefile ├── README.md ├── code │ ├── 00 │ │ ├── 00-new-style-example.py │ │ ├── 01-old-style-example.py │ │ ├── 02-new-style-raise.py │ │ └── 03-old-style-raise.py │ ├── 01 │ │ ├── 10-super-example-error.py │ │ ├── 11-super-example-py2k-0.py │ │ ├── 12-super-example-py2k-1.py │ │ ├── 13-super-example-py3k.py │ │ ├── 14-multiple-inheritance-0.py │ │ ├── 15-multiple-inheritance-1.py │ │ └── 16-multiple-inheritance-2.py │ ├── 02 │ │ ├── 20-self-example.py │ │ ├── 21-this-example.py │ │ ├── 22-if-self-were-optional.py │ │ ├── 23-self-error.py │ │ ├── 24-method-call-equivalency.py │ │ └── 25-self-add-method.py │ ├── 03 │ │ ├── 30-class-variable-example-0.py │ │ ├── 31-class-variable-example-1.py │ │ ├── 32-defining-constants-0.py │ │ ├── 33-defining-constants-1.py │ │ ├── 34-initializing-to-None-0.py │ │ ├── 35-initializing-to-None-1.py │ │ └── 36-self-or-class-name.py │ ├── 04 │ │ ├── 40-private-example.py │ │ ├── 41-private-bad-idea.py │ │ ├── 42-method-with-same-name.py │ │ ├── 43-mangled-example-0.py │ │ ├── 44-mangled-example-1.py │ │ ├── 45-mangled-why-we-need-them-0.py │ │ ├── 46-mangled-why-we-need-them-1.py │ │ └── 47-mangled-why-we-need-them-2.py │ ├── 05 │ │ ├── 50-staticmethod-example-0.py │ │ ├── 51-staticmethod-example-1.py │ │ ├── 52-staticmethod-example-2.py │ │ ├── 53-new-object-problem-0.py │ │ ├── 54-new-object-problem-1.py │ │ ├── 55-new-object-problem-2.py │ │ ├── 56-new-object-problem-3.py │ │ ├── 57-classmethod-example-0.py │ │ └── 58-classmethod-example-1.py │ ├── 06 │ │ ├── 600-getter-example-0.py │ │ ├── 601-getter-example-1.py │ │ ├── 602-setter-example-0.py │ │ ├── 603-setter-example-1.py │ │ ├── 604-setters-getters-example.py │ │ ├── 605-properties-example.py │ │ ├── 606-property-fget.py │ │ ├── 607-property-fset.py │ │ ├── 608-property-deleter-usage.py │ │ ├── 608-property-deleter.py │ │ ├── 609-fget-docstring.py │ │ ├── 610-name-unmatch.py │ │ ├── 611-property-function.py │ │ ├── 612-setter-and-deleter.py │ │ └── 613-deleter-error.py │ ├── 07 │ │ ├── 700-neither-str-nor-repr.py │ │ ├── 701-str-example-0.py │ │ ├── 702-str-example-1.py │ │ ├── 703-repr-undefined.py │ │ ├── 704-repr-example.py │ │ ├── 705-repr-no-str.py │ │ └── 706-datetime-str-and-repr.py │ ├── 08 │ │ ├── 800-why-we-need-namedtuples-0.py │ │ ├── 801-why-we-need-namedtuples-1.py │ │ ├── 802-why-we-need-namedtuples-2.py │ │ ├── 803-why-we-need-namedtuples-3.py │ │ ├── 804-Point-with-namedtuple.py │ │ ├── 805-namedtuple-explained.py │ │ ├── 806-namedtuple-field_names.py │ │ ├── 807-namedtuple-invalid-identifier.py │ │ ├── 808-namedtuple-rename.py │ │ ├── 809-namedtuple-why-typename.py │ │ ├── 810-Point-own-methods-0.py │ │ ├── 811-Point-own-methods-1.py │ │ ├── 812-Point-own-methods-2.py │ │ ├── 813-Point-own-methods-3.py │ │ ├── 814-namedtuple-verbose.py │ │ ├── 815-namedtuple-asdict.py │ │ └── 816-namedtuple-replace.py │ └── 09 │ │ ├── 900-why-we-need-new-0.py │ │ ├── 901-why-we-need-new-1.py │ │ ├── 902-why-we-need-new-2.py │ │ ├── 903-why-we-need-new-3.py │ │ ├── 904-return-from-init-0.py │ │ ├── 905-return-from-init-1.py │ │ ├── 906-immutable-init.py │ │ ├── 907-Pesos-with-new-0.py │ │ ├── 908-Pesos-with-new-1.py │ │ ├── 909-Pesos-with-new-2.py │ │ ├── 910-AnswerToEverything-0.py │ │ └── 911-AnswerToEverything-1.py ├── cover.tex ├── epilogue.tex ├── generate-outputs.py ├── intro.py ├── intro.tex ├── pics │ ├── captain-obvious.jpg │ ├── cover.svg │ ├── dijkstra-2.jpg │ ├── dijkstra.jpg │ ├── dog-no-idea-2.jpg │ ├── dog-no-idea.jpg │ ├── dont-want-to-live-on-this-planet.png │ ├── game-developer-expectation.jpg │ ├── game-developer-reality.jpg │ ├── like-a-sir.png │ ├── pair-programming-expectation.jpg │ ├── pair-programming-reality.jpg │ └── programmer-two-states.png ├── puntos │ ├── 00.tex │ ├── 01.tex │ ├── 02.tex │ ├── 03.tex │ ├── 04.tex │ ├── 05.tex │ ├── 06.tex │ ├── 07.tex │ ├── 08.tex │ └── 09.tex └── python-classes.tex ├── [2015] Dijkstra is My Shepherd, I Lack Nothing ├── README.rst ├── pics │ └── portada.png └── python-dijkstra.pdf ├── [2016] Kung Fu at Dawn with Itertools ├── README.rst ├── images │ ├── 804f593851328b126f24e1c4ec386451a5bef09b.png │ ├── Battle_Cry.jpg │ ├── Bruce_Lee_Statue.jpg │ ├── Bulletproof_Bruce_Lee.jpg │ ├── Dashi.jpg │ ├── Deflected_Kick.jpg │ ├── Front_Kalaripayattu.jpg │ ├── Front_Kalaripayattu.svg │ ├── Shi_DeRu_and_Shi_DeYang.jpg │ ├── Steven_Ho_540_Kick.jpg │ ├── Wushu_Dao.jpg │ ├── curve-one.svg │ ├── curve-three.svg │ └── curve-two.svg └── kung-fu-itertools.ipynb ├── [2016] The Closures that Moved Spielberg ├── Front.jpg ├── README.md └── python-closures.pdf ├── [2018] 'is' versus == [lightning] ├── Front.jpg ├── Front.svg ├── README.md └── is-versus-equals.ipynb ├── [2018] Hashable Objects ├── Makefile ├── README.md ├── images │ ├── Caravan_in_the_desert.jpg │ ├── Cover.jpg │ ├── Cover.svg │ ├── Hash_collision_resolved_by_open_addressing.svg │ ├── Hash_collision_resolved_by_separate_chaining.svg │ ├── adventure-arid-barren-206724.jpg │ ├── backlit-dawn-desert-998649.jpg │ ├── dawn-desert-dunes-69794.jpg │ └── rhodes-mighty-dict.jpg ├── python-hashable.ipynb └── slideshow.py ├── [2018] Python Heaps-ters ├── Makefile ├── README.md ├── WebVTT │ └── python-heaps-ters-spanish.vtt ├── images │ ├── adult-agreement-beard-541526.jpg │ ├── adult-beard-blur-551657.jpg │ ├── adult-beard-boy-573564.jpg │ ├── adult-beard-businessman-401685.jpg │ ├── beard-corporate-facial-hair-556962.jpg │ ├── binary-heap-with-array-implementation.jpg │ ├── binary_tree_in_array.svg │ ├── comparison_computational_complexity.svg │ ├── cover.jpg │ ├── cover.svg │ ├── deletion │ │ ├── 00-highlight-root.svg │ │ ├── 01-root-is-gone.svg │ │ ├── 02-highlight-last-node.svg │ │ ├── 03-show-last-node-becomes-root.svg │ │ ├── 04-last-node-becomes-root.svg │ │ ├── 05-highlight-left-child.svg │ │ ├── 06-highlight-right-child.svg │ │ ├── 07-mark-left-child.svg │ │ ├── 08-swap-root-and-left-child.svg │ │ ├── 09-clear-left-child.svg │ │ ├── 10-highlight-left-grandchild.svg │ │ ├── 11-highlight-right-grandchild.svg │ │ ├── 12-mark-right-grandchild.svg │ │ ├── 13-swap-root-and-right-grandchild.svg │ │ ├── 14-clear-right-grandchild.svg │ │ └── 15-clear-original-root.svg │ ├── generate-graphviz.ipynb │ ├── insertion │ │ ├── 00-simple-heap-empty-slot.svg │ │ ├── 01a-highlight-next-free-slot.svg │ │ ├── 01b-show-path-to-next-free-slot.svg │ │ ├── 02-add-new-node.svg │ │ ├── 02-simple-heap-empty-slot.svg │ │ ├── 03-highlight-ancestor.svg │ │ ├── 04-mark-ancestor.svg │ │ ├── 05-swap-node-and-ancestor.svg │ │ ├── 06-clear-ancestor.svg │ │ ├── 07-highlight-ancestor.svg │ │ ├── 08-clear-root.svg │ │ └── 09-clear-new-node.svg │ ├── root │ │ └── highlight-root.svg │ └── simple │ │ └── heap.svg ├── lots-of-numbers.txt └── python-heaps-ters.ipynb └── [2018] Taking the Garbage Out ├── Front.jpg ├── README.md └── python-garbage-collection.pdf /.github/workflows/forty-features.yml: -------------------------------------------------------------------------------- 1 | name: Compile vterron.xyz/forty Beamer slides to PDF 2 | 3 | on: [push] 4 | 5 | env: 6 | BASENAME: forty-features 7 | WORKING_DIR: "[2013] Forty Features of Python that You May Not Know" 8 | 9 | jobs: 10 | build_job: 11 | name: Build PDF slides 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Git repository checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: LaTeX compilation 19 | uses: dante-ev/latex-action@master 20 | with: 21 | root_file: ${{ env.BASENAME }}.tex 22 | working_directory: ${{ env.WORKING_DIR }} 23 | 24 | - name: Upload PDF artifact 25 | uses: actions/upload-artifact@v2 26 | with: 27 | name: slides-pdf 28 | # The path hierarchy is preserved after the first wildcard pattern. 29 | path: "**/${{ env.BASENAME }}.pdf" 30 | 31 | upload_job: 32 | name: Upload PDF slides 33 | needs: build_job 34 | runs-on: ubuntu-latest 35 | 36 | steps: 37 | - name: Configure AWS credentials 38 | uses: aws-actions/configure-aws-credentials@v1 39 | with: 40 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 41 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 42 | aws-region: ${{ secrets.AWS_REGION }} 43 | 44 | - name: Download PDF artifact 45 | uses: actions/download-artifact@v4.1.7 46 | with: 47 | name: slides-pdf 48 | 49 | - name: Upload PDF slides to Amazon S3 50 | working-directory: ${{ env.WORKING_DIR }} 51 | run: | 52 | aws s3 cp ${{ env.BASENAME }}.pdf ${{ secrets.AWS_S3_BUCKET }} 53 | -------------------------------------------------------------------------------- /.github/workflows/python-classes.yml: -------------------------------------------------------------------------------- 1 | name: Compile vterron.xyz/classes Beamer slides to PDF 2 | 3 | on: [push] 4 | 5 | env: 6 | BASENAME: python-classes 7 | WORKING_DIR: "[2014] Classes in Python: You're Doing it Wrong" 8 | 9 | jobs: 10 | build_job: 11 | name: Build PDF slides 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Git repository checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: Install Python 2 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: '2.7.18' 22 | 23 | - name: Install pdfLaTeX 24 | run: sudo apt-get install -y texlive-latex-extra 25 | 26 | - name: LaTeX compilation 27 | working-directory: ${{ env.WORKING_DIR }} 28 | run: make pdf 29 | 30 | # In upload-artifact action below we can't upload an artifact whose path includes a colon. 31 | - name: Move PDF artifact to Git repository root directory. 32 | working-directory: ${{ env.WORKING_DIR }} 33 | run: mv ${{ env.BASENAME }}.pdf .. -v 34 | 35 | - name: Upload PDF artifact 36 | uses: actions/upload-artifact@v2 37 | with: 38 | name: slides-pdf 39 | path: ${{ env.BASENAME }}.pdf 40 | if-no-files-found: error 41 | 42 | upload_job: 43 | name: Upload PDF slides 44 | needs: build_job 45 | runs-on: ubuntu-latest 46 | 47 | steps: 48 | - name: Configure AWS credentials 49 | uses: aws-actions/configure-aws-credentials@v1 50 | with: 51 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 52 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 53 | aws-region: ${{ secrets.AWS_REGION }} 54 | 55 | - name: Download PDF artifact 56 | uses: actions/download-artifact@v4.1.7 57 | with: 58 | name: slides-pdf 59 | 60 | - name: Upload PDF slides to Amazon S3 61 | run: | 62 | aws s3 cp ${{ env.BASENAME }}.pdf ${{ secrets.AWS_S3_BUCKET }} 63 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "PyConES-2017"] 2 | path = [2017] Metaclasses: Exactly What and (Especially) Why 3 | url = https://github.com/pablogsal/pycones2017.git 4 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/Makefile: -------------------------------------------------------------------------------- 1 | # Inspired by Stephan Bourduas's LaTeX Makefile: 2 | # http://www.iml.ece.mcgill.ca/~stephan/node/13 3 | 4 | SHELL := /bin/bash 5 | 6 | PDFLATEX=pdflatex 7 | PDFLATEX_OPTS=-interaction=nonstopmode -halt-on-error 8 | 9 | BASENAME=forty-features 10 | TEX_FILE=${BASENAME}.tex 11 | PDF_FILE=${BASENAME}.pdf 12 | 13 | .PHONY: all pdf clean 14 | 15 | all : pdf cover 16 | 17 | cover: pdf 18 | pdf2svg $(PDF_FILE) pics/cover.svg 19 | 20 | pdf: $(TEX_FILE) 21 | $(PDFLATEX) $(PDFLATEX_OPTS) $(TEX_FILE) 22 | $(PDFLATEX) $(PDFLATEX_OPTS) $(TEX_FILE) 23 | 24 | clean: 25 | rm -fv *.{aux,log,nav,out,snm,toc,vrb} 26 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/README.md: -------------------------------------------------------------------------------- 1 | The slides of the talk I gave at [PyConES 2013](http://2013.es.pycon.org/) (Madrid, Spain). 2 | 3 | [![Front](./pics/cover.svg)][pdf] 4 | 5 | They are also [available as a PDF][pdf], always up-to-date via [a GitHub action](../.github/workflows/forty-features.yml). 6 | 7 | - Title: *`["Python"] * 40` — Forty Features of Python that You May Not Know* 8 | - Language: Spanish 9 | - License: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 10 | 11 | [pdf]: https://static.vterron.xyz/forty-features.pdf 12 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/cover.tex: -------------------------------------------------------------------------------- 1 | { 2 | \usebackgroundtemplate{\includegraphics[height=1.0\paperheight]{pics/un-palo.jpg}} 3 | 4 | \begin{frame}[plain] 5 | \vspace{6.25cm} 6 | \begin{TitleBox} 7 | {\LARGE \inserttitle} \\ 8 | {\small Cuarenta características de Python que \textcolor{darkerred}{quizás} no conoces \\ 9 | \insertauthor \enspace --- \thinspace \url{http://vterron.xyz/forty}} 10 | \end{TitleBox} 11 | \end{frame} 12 | } 13 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/02.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}{2. \large Encadenamiento de operadores lógicos} 5 | \begin{alertblock}{En vez de escribir} 6 | \centering \LARGE x => y and y < z 7 | \end{alertblock} 8 | 9 | \small 10 | \begin{center} 11 | A diferencia de C, todos los operadores lógicos tienen la misma 12 | prioridad, y pueden ser encadenados de forma arbitraria. 13 | \end{center} 14 | 15 | \begin{block}{Mucho mejor} 16 | \centering \LARGE x <= y < z 17 | \end{block} 18 | 19 | \small 20 | \begin{center} 21 | Las dos expresiones de arriba son equivalentes, aunque en la 22 | segunda \structure{y} sólo se evalúa una vez. En ambos casos, 23 | \structure{z} no llega a evaluarse si no se cumple que 24 | \structure{x <= y} (\emph{lazy evaluation}). 25 | \end{center} 26 | \end{frame} 27 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/04.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{4. int(True) == 1} 5 | \large 6 | \begin{alertblock}{} 7 | \centering 8 | El valor numérico de \structure{True} es 1; el de \structure{False}, 0 9 | \end{alertblock} 10 | 11 | \begin{exampleblock}{} 12 | \small 13 | \begin{lstlisting} 14 | >>> int(True) 15 | 1 16 | >>> int(False) 17 | 0 18 | >>> 37 + True 19 | 38 20 | >>> 7 / False 21 | Traceback (most recent call last): 22 | File "", line 1, in 23 | ZeroDivisionError: float division 24 | \end{lstlisting} 25 | \end{exampleblock} 26 | \end{frame} 27 | 28 | \begin{frame}[fragile]{4. int(True) == 1} 29 | \large 30 | \begin{block}{} 31 | \centering 32 | De hecho, la clase \structure{bool} hereda de \structure{int} 33 | \end{block} 34 | 35 | \begin{exampleblock}{} 36 | \small 37 | \begin{lstlisting} 38 | >>> issubclass(bool, int) 39 | True 40 | >>> isinstance(True, int) 41 | True 42 | >>> bool.mro() 43 | [, , ] 44 | \end{lstlisting} 45 | \end{exampleblock} 46 | 47 | \small 48 | \begin{block}{\centering PEP 285: Adding a bool type [2002]} 49 | \centering \url{http://www.python.org/dev/peps/pep-0285/} 50 | \end{block} 51 | \end{frame} 52 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/05.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{5. import this} 5 | \Large 6 | \begin{block}{} 7 | \centering El Zen de Python 8 | \end{block} 9 | 10 | \begin{exampleblock}{\small Los principios filosóficos en los que se cimenta Python} 11 | \tiny 12 | \begin{lstlisting} 13 | >>> import this 14 | The Zen of Python, by Tim Peters 15 | 16 | Beautiful is better than ugly. 17 | Explicit is better than implicit. 18 | Simple is better than complex. 19 | Complex is better than complicated. 20 | Flat is better than nested. 21 | Sparse is better than dense. 22 | Readability counts. 23 | [...] 24 | \end{lstlisting} 25 | \end{exampleblock} 26 | 27 | \small 28 | \begin{block}{\centering PEP 20: The Zen of Python [2004]} 29 | \centering \url{http://www.python.org/dev/peps/pep-0020/} 30 | \end{block} 31 | \end{frame} 32 | 33 | \begin{frame}[fragile]{5. import this} 34 | \small 35 | \begin{center} 36 | Algo bastante más desconocido: el contenido del módulo 37 | \structure{this.py} está cifrado con el algoritmo 38 | \structure{ROT13} --- cada letra sustituida por la que está trece 39 | posiciones por delante en el alfabeto: 40 | \end{center} 41 | 42 | \begin{exampleblock}{} 43 | \tiny 44 | \begin{lstlisting} 45 | >>> import inspect 46 | >>> print inspect.getsource(this) 47 | s = """Gur Mra bs Clguba, ol Gvz Crgref 48 | 49 | Ornhgvshy vf orggre guna htyl. 50 | Rkcyvpvg vf orggre guna vzcyvpvg. 51 | Fvzcyr vf orggre guna pbzcyrk. 52 | Pbzcyrk vf orggre guna pbzcyvpngrq. 53 | Syng vf orggre guna arfgrq. 54 | Fcnefr vf orggre guna qrafr. 55 | Ernqnovyvgl pbhagf. 56 | [...] 57 | \end{lstlisting} 58 | \end{exampleblock} 59 | 60 | \scriptsize 61 | \begin{block}{\centering this and The Zen of Python} 62 | \centering 63 | \url{http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html} 64 | \end{block} 65 | \end{frame} 66 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/06.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}{6. El módulo antigravedad} 5 | \Large 6 | \begin{block}{} 7 | \centering import antigravity 8 | \end{block}{} 9 | 10 | \begin{figure} 11 | \centering 12 | \includegraphics[height=4cm]{pics/xkcd-353.png} 13 | \caption{\url{http://xkcd.com/353/}} 14 | \end{figure} 15 | 16 | \small 17 | \begin{alertblock}{} 18 | \centering 19 | Añadido en Python 3, pero también está disponible en Python 2.7 20 | \end{alertblock} 21 | \end{frame} 22 | 23 | \begin{frame}[fragile]{6. El módulo antigravedad} 24 | \begin{exampleblock}{\small antigravity.py} 25 | \small 26 | \begin{lstlisting} 27 | >>> print inspect.getsource(antigravity) 28 | import webbrowser 29 | webbrowser.open("http://xkcd.com/353/") 30 | \end{lstlisting} 31 | \end{exampleblock} 32 | 33 | \begin{center} 34 | \small 35 | En Py3K el módulo \structure{antigravity} incluye la función 36 | \structure{geohash()}, referencia a otra viñeta de XKCD en la que 37 | se describe un algoritmo que genera coordenadas en base a la fecha 38 | y tu posición actual: \url{http://xkcd.com/426/} 39 | \end{center} 40 | 41 | \small 42 | \begin{block}{\centering The History of Python - import antigravity} 43 | \centering 44 | \scriptsize 45 | \url{http://python-history.blogspot.com.es/2010/06/import-antigravity.html} 46 | \end{block} 47 | \end{frame} 48 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/07.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}{7. Bloques de código} 5 | \small 6 | \begin{center} 7 | En Python los bloques de código se definen mediante el 8 | \structure{sangrado}, no utilizando palabras clave, como en 9 | Fortran, o llaves, como en C. Ya que hay a quien le desagrada, e 10 | incluso odia esta característica, gracias al módulo 11 | \structure{\_\_future\_\_} es posible habilitar el uso de las 12 | llaves para la delimitación de bloques. 13 | \end{center} 14 | 15 | \Large 16 | \begin{alertblock}{} 17 | \centering 18 | from \_\_future\_\_ import braces 19 | \end{alertblock} 20 | 21 | \vspace{0.5cm} 22 | 23 | \small 24 | \begin{block}{\centering Python White Space Discussion} 25 | \centering 26 | \url{http://c2.com/cgi/wiki?PythonWhiteSpaceDiscussion} 27 | \end{block} 28 | \end{frame} 29 | 30 | \begin{frame}[fragile]{7. Bloques de código} 31 | \begin{exampleblock}{} 32 | \small 33 | \begin{lstlisting}[escapechar=!] 34 | >>> from __future__ import braces 35 | File "", line 1 36 | !\color{red}{SyntaxError: not a chance} 37 | \end{lstlisting} 38 | \end{exampleblock} 39 | 40 | \begin{figure} 41 | \centering 42 | \includegraphics[height=4.5cm]{pics/trollface.png} 43 | \end{figure} 44 | \end{frame} 45 | 46 | \begin{frame}[fragile]{7. Bloques de código} 47 | \begin{alertblock}{} 48 | \centering 49 | Pero, si \structure{de verdad} quieres usarlos, ¡hay una forma! 50 | \end{alertblock} 51 | 52 | \begin{exampleblock}{} 53 | \small 54 | \begin{lstlisting}[escapechar=!] 55 | if foo: !\color{blue}{\#}!{ 56 | print "It's True" 57 | !\color{blue}{\#}!} 58 | else: !\color{blue}{\#}!{ 59 | print "It's False" 60 | !\color{blue}{\#}!} 61 | \end{lstlisting} 62 | \end{exampleblock} 63 | 64 | \small 65 | \begin{block}{\centering Is it true that I can't use curly braces in Python?} 66 | \centering 67 | \url{http://stackoverflow.com/a/1936210/184363} 68 | \end{block} 69 | \end{frame} 70 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/08.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{8. Concatenación eficiente de cadenas} 5 | \small 6 | \begin{exampleblock} 7 | {Tenemos varias cadenas de texto que queremos unir:} 8 | \small 9 | \begin{lstlisting} 10 | >>> palabras = "uno", "dos", "tres" 11 | >>> resultado = "" 12 | >>> for p in palabras: 13 | >>> resultado += p 14 | >>> resultado 15 | 'unodostres' 16 | \end{lstlisting} 17 | \end{exampleblock} 18 | 19 | \begin{block}{} 20 | Las cadenas de texto en Python son \structure{inmutables}, por lo 21 | que cada vez que asignamos una cadena a una variable \structure{un 22 | nuevo objeto} es creado en memoria. En este código estamos 23 | calculando, almacenando y desechando cada paso intermedio. 24 | Eso es inaceptablemente lento. 25 | \end{block} 26 | \end{frame} 27 | 28 | \begin{frame}[fragile]{8. Concatenación eficiente de cadenas} 29 | \begin{alertblock} 30 | {\centering \small 31 | La forma Pythónica de concatenar cadenas es así:} 32 | \centering \Large resultado = "".join(palabras) 33 | \end{alertblock} 34 | 35 | \small 36 | \begin{center} 37 | El método \structure{str.join(iterable)} devuelve una cadena que 38 | es la concatenación de las cadenas en \structure{iterable}, 39 | utilizando como separador entre los elementos la cadena que llama 40 | al método. 41 | \end{center} 42 | 43 | \begin{exampleblock}{} 44 | \begin{lstlisting} 45 | >>> palabras = "uno", "dos", "tres" 46 | >>> "-".join(palabras) 47 | 'uno-dos-tres' 48 | \end{lstlisting} 49 | \end{exampleblock} 50 | 51 | \small 52 | \begin{center} 53 | Y lo hace \structure{de una única pasada} --- rápido y eficiente. 54 | \end{center} 55 | \end{frame} 56 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/09.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{9. printf en Python} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | Los objetos str y unicode tienen el \structure{operador \%}, que 9 | nos permite usar la sintaxis del antediluviano, presente en todos 10 | los lenguajes, \structure{printf()}, para controlar exactamente 11 | cómo se muestra una cadena de texto. 12 | \end{block} 13 | 14 | \footnotesize 15 | \begin{exampleblock}{} 16 | \begin{lstlisting} 17 | >>> print math.pi 18 | 3.14159265359 19 | >>> "%.2f" % math.pi 20 | 3.14 21 | >>> "%05.2f" % math.pi 22 | 03.14 23 | >>> potencia = math.e ** 100 24 | >>> "%.2f ^ %.2f = %.4g" % (math.e, 100, potencia) 25 | '2.72 ^ 100.00 = 2.688e+43' 26 | \end{lstlisting} 27 | \end{exampleblock} 28 | \end{frame} 29 | 30 | \begin{frame}[fragile]{9. printf en Python} 31 | \footnotesize 32 | \begin{exampleblock}{} 33 | \begin{lstlisting} 34 | >>> "%s por %d es %f" % ("tres", 2, 6.0) 35 | 'tres por 2 es 6.000000' 36 | >>> "%0*d" % (5, 3) 37 | '00003' 38 | >>> "%+.*f" % (5, math.pi) 39 | '+3.14159' 40 | \end{lstlisting} 41 | \end{exampleblock} 42 | 43 | \begin{alertblock}{} 44 | \centering 45 | \small 46 | No obstante, desde Python 2.6 lo recomendable es usar 47 | \structure{str.format()}: más sofisticado, flexible, extensible y 48 | que puede trabajar con tuplas y diccionarios de forma natural. ¡El 49 | operador de \% para el formateo de cadenas se considera 50 | \structure{obsoleto}! 51 | \end{alertblock} 52 | 53 | \begin{block} 54 | {\centering PEP 3101: Advanced String Formatting [2006]} 55 | \centering \url{http://www.python.org/dev/peps/pep-3101/} 56 | \end{block} 57 | \end{frame} 58 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/10.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{10. str.format()} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | Tanto el operador \structure{\%} como \structure{str.format()} 9 | permiten acceder a argumentos por su nombre, lo que es 10 | especialmente útil si necesitamos usar más de una vez la misma 11 | cadena. Pero \structure{str.format()} puede hacer muchas cosas 12 | más, como acceder a atributos de los argumentos, o hacer 13 | conversiones a str() y repr(). 14 | \end{block} 15 | 16 | \footnotesize 17 | \begin{exampleblock} 18 | {Acceso a los argumentos por posición} 19 | \begin{lstlisting} 20 | >>> '{0}{1}{0}'.format('abra', 'cad') 21 | 'abracadabra' 22 | \end{lstlisting} 23 | \end{exampleblock} 24 | 25 | \begin{exampleblock} 26 | {Acceso a los atributos de un argumento por posición} 27 | \begin{lstlisting} 28 | >>> "Parte real: {0.real}".format(2+3j) 29 | 'Parte real: 2.0' 30 | \end{lstlisting} 31 | \end{exampleblock} 32 | \end{frame} 33 | 34 | \begin{frame}[fragile]{10. str.format()} 35 | \footnotesize 36 | \begin{exampleblock} 37 | {Acceso a argumentos por nombre} 38 | \scriptsize 39 | \begin{lstlisting} 40 | >>> kwargs = {'nombre' : 'Pedro', 'apellido' : 'Medina'} 41 | >>> "{nombre} {apellido} se llama {nombre}".format(kwargs) 42 | 'Pedro Medina se llama Pedro' 43 | \end{lstlisting} 44 | \end{exampleblock} 45 | 46 | \begin{exampleblock} 47 | {Acceso a atributos de argumentos por nombre} 48 | \scriptsize 49 | \begin{lstlisting} 50 | >>> kwargs = {'numero' : 1+5j} 51 | >>> "Parte imaginaria: {numero.imag}".format(**kwargs) 52 | 'Parte imaginaria: 5.0' 53 | \end{lstlisting} 54 | \end{exampleblock} 55 | 56 | \small 57 | \begin{block} 58 | {\centering Format Specification Mini-Language} 59 | \footnotesize 60 | \centering 61 | \url{http://docs.python.org/2/library/string.html#formatstrings} 62 | \end{block} 63 | \end{frame} 64 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/11.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{11. Cadenas multilínea} 5 | 6 | \begin{block}{} 7 | \centering \large 8 | Una opción es usar \structure{barras invertidas} 9 | \end{block} 10 | 11 | \begin{exampleblock}{} 12 | \scriptsize 13 | \begin{lstlisting} 14 | >>> parrafo = "En un lugar de la Mancha, de cuyo nombre " \ 15 | ... "no quiero acordarme, no ha mucho tiempo " \ 16 | ... "que vivía un hidalgo de los de lanza en " \ 17 | ... "astillero, adarga antigua, rocín flaco y " \ 18 | ... "galgo corredor." 19 | >>> parrafo[:24] 20 | 'En un lugar de la Mancha' 21 | >>> parrafo[-17:] 22 | 'y galgo corredor.' 23 | \end{lstlisting} 24 | \end{exampleblock} 25 | 26 | \begin{alertblock}{} 27 | \centering 28 | \small 29 | Pero, en el caso de trabajar con \structure{cadenas muy largas}, 30 | puede ser molesto tener que \structure{terminar cada línea con 31 | \textbackslash}, sobre todo porque nos impide reformatear el 32 | párrafo con nuestro entorno de desarrollo o editor de texto --- 33 | ¡Emacs, por supuesto! 34 | \end{alertblock} 35 | \end{frame} 36 | 37 | \begin{frame}[fragile]{11. Cadenas multilínea} 38 | 39 | \begin{block}{} 40 | \centering 41 | Las comillas triples respetan \structure{todo} lo que hay dentro 42 | de ellas, incluyendo \structure{saltos de línea}. No es necesario 43 | escapar nada: todo se incluye directamente en la cadena. 44 | \end{block} 45 | 46 | \begin{exampleblock}{} 47 | \scriptsize 48 | %Escape triple quotes; otherwise string is italicized 49 | \begin{lstlisting}[escapechar=!] 50 | >>> parrafo = !"""!En un lugar de la Mancha, 51 | ... de cuyo nombre no quiero 52 | ... acordarme 53 | ... 54 | ... !"""! 55 | >>> print parrafo 56 | En un lugar de la Mancha, 57 | de cuyo nombre no quiero 58 | acordarme 59 | 60 | 61 | >>> 62 | \end{lstlisting} 63 | \end{exampleblock} 64 | \end{frame} 65 | 66 | \begin{frame}[fragile]{11. Cadenas multilínea} 67 | 68 | \begin{alertblock}{} 69 | \small 70 | \centering 71 | Una opción menos conocida es que podemos dividir nuestra cadena en 72 | líneas, una por línea, y \structure{rodearlas con paréntesis}. 73 | Python evalúa lo que hay dentro de los mismos y de forma 74 | automática las concatena: 75 | \end{alertblock} 76 | 77 | \begin{exampleblock}{} 78 | \scriptsize 79 | \begin{lstlisting} 80 | >>> parrafo = ("Es, pues, de saber, que este " 81 | ... "sobredicho hidalgo, los ratos " 82 | ... "que estaba ocioso") 83 | >>> len(parrafo.split()) 84 | 13 85 | \end{lstlisting} 86 | \end{exampleblock} 87 | 88 | \small 89 | \begin{exampleblock} 90 | {Un ejemplo más sencillo:} 91 | \begin{lstlisting} 92 | >>> "uno" "dos" 93 | 'unodos' 94 | \end{lstlisting} 95 | \end{exampleblock} 96 | \end{frame} 97 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/12.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile] 5 | {\large 12. Listas por comprensión vs generadores} 6 | \begin{block}{} 7 | \small 8 | \centering 9 | Las listas por comprensión nos permiten construir, \structure{en 10 | un único paso}, una lista donde cada elemento es el resultado de 11 | aplicar \structure{algunas operaciones} a todos (o algunos de) los 12 | miembros de otra secuencia o iterable. 13 | \end{block} 14 | 15 | \footnotesize 16 | \begin{exampleblock} 17 | {Por ejemplo, para calcular el cuadrado de los números [0, 9]:} 18 | \begin{lstlisting} 19 | >>> g = [x ** 2 for x in range(10)] 20 | [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 21 | \end{lstlisting} 22 | \end{exampleblock} 23 | 24 | \begin{exampleblock} 25 | {Esto es equivalente a:} 26 | \begin{lstlisting} 27 | >>> resultado = [] 28 | >>> for x in range(10): 29 | ... resultado.append(x ** 2) 30 | \end{lstlisting} 31 | \end{exampleblock} 32 | \end{frame} 33 | 34 | \begin{frame}[fragile] 35 | {\large 12. Listas por comprensión vs generadores} 36 | 37 | \begin{alertblock}{} 38 | \centering 39 | El problema, a veces, es que las listas por comprensión 40 | construyen... pues eso, una lista, almacenando \structure{todos 41 | los valores en memoria} a la vez. 42 | \end{alertblock} 43 | 44 | \footnotesize 45 | \begin{exampleblock} 46 | {No intentéis esto en casa} 47 | \begin{lstlisting} 48 | >>> [x ** 2 for x in xrange(1000000000000000)] 49 | # Tu ordenador explota 50 | \end{lstlisting} 51 | \end{exampleblock} 52 | \end{frame} 53 | 54 | \begin{frame}[fragile] 55 | {\large 12. Listas por comprensión vs generadores} 56 | \small 57 | \begin{block}{} 58 | \centering 59 | Si sólo necesitamos los valores una vez, y de uno en uno, podemos 60 | utilizar una \structure{expresión generadora}: son idénticos a las 61 | listas por comprensión, pero usando \structure{paréntesis}. 62 | \end{block} 63 | 64 | \footnotesize 65 | \begin{exampleblock}{} 66 | \begin{lstlisting} 67 | >>> cuadrados = (x ** 2 for x in range(1, 11)) 68 | >>> cuadrados 69 | at 0x7f8b82504eb0> 70 | >>> next(cuadrados) 71 | 1 72 | >>> next(cuadrados) 73 | 4 74 | \end{lstlisting} 75 | \end{exampleblock} 76 | 77 | \small 78 | \begin{block} 79 | {\centering PEP 289: Generator Expressions} 80 | \centering \url{http://www.python.org/dev/peps/pep-0289/} 81 | \end{block} 82 | \end{frame} 83 | 84 | \begin{frame}[fragile] 85 | {\large 12. Listas por comprensión vs generadores} 86 | \footnotesize 87 | \begin{exampleblock} 88 | {Equivalente a:} 89 | \begin{lstlisting} 90 | >>> def cuadrados(seq): 91 | ... for x in seq: 92 | ... yield x ** 2 93 | ... 94 | >>> g = cuadrados(range(1, 11)) 95 | >>> next(g) 96 | 1 97 | >>> next(g) 98 | 4 99 | \end{lstlisting} 100 | \end{exampleblock} 101 | 102 | \small 103 | \begin{block} 104 | {\centering Generator Tricks for Systems Programmers (David M. Beazley)} 105 | \centering \url{http://www.dabeaz.com/generators/} 106 | \end{block} 107 | \end{frame} 108 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/13.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{13. \large Comprensión de conjuntos y diccionarios} 5 | \begin{block}{} 6 | \centering 7 | En Python 2.7.x+ y 3.x+ podemos crear no sólo listas, sino también 8 | \structure{conjuntos} y \structure{diccionarios} por comprensión. 9 | \end{block} 10 | 11 | \scriptsize 12 | \begin{exampleblock} 13 | {Un conjunto con los múltiplos de siete <= 100:} 14 | \begin{lstlisting} 15 | >>> {x for x in range(1, 101) if not x % 7} 16 | set([98, 35, 70, 7, 42, 77, 14, 49, 84, 21, 56, 91, 28, 63]) 17 | \end{lstlisting} 18 | \end{exampleblock} 19 | 20 | \begin{exampleblock} 21 | {Otra forma de hacerlo:} 22 | \begin{lstlisting} 23 | >>> mult7 = set(x for x in range(1, 101) if not x % 7) 24 | >>> len(mult7) 25 | 14 26 | >>> 25 in mult7 27 | False 28 | \end{lstlisting} 29 | \end{exampleblock} 30 | \end{frame} 31 | 32 | \begin{frame}[fragile]{13. \large Comprensión de conjuntos y diccionarios} 33 | \scriptsize 34 | \begin{exampleblock} 35 | {Un diccionario con el cubo de los números [0, 9]:} 36 | \begin{lstlisting} 37 | >>> cubos = {x : x ** 3 for x in range(10)} 38 | >>> cubos[2] 39 | 8 40 | >>> cubos[8] 41 | 512 42 | \end{lstlisting} 43 | \end{exampleblock} 44 | 45 | \begin{exampleblock} 46 | {Otra forma de hacerlo:} 47 | \begin{lstlisting} 48 | >>> dict((x, x ** 3) for x in range(5)) 49 | {0: 0, 1: 1, 2: 8, 3: 27, 4: 64} 50 | \end{lstlisting} 51 | \end{exampleblock} 52 | 53 | \small 54 | \begin{block} 55 | {\centering PEP 274: Dict Comprehensions [2001]} 56 | \centering \url{http://www.python.org/dev/peps/pep-0274/} 57 | \end{block} 58 | \end{frame} 59 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/15.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{15. pow(x, y, z)} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | La función \structure{pow()} acepta, opcionalmente, un tercer 9 | argumento, \structure{z}. En caso de especificarse, la función 10 | devuelve \structure{pow(x, y) \% z}. No es sólo práctico en 11 | algunos escenarios, sino que su implementación es más rápida que 12 | calcularlo nosotros en dos pasos. 13 | \end{block} 14 | 15 | \footnotesize 16 | \begin{exampleblock}{} 17 | \begin{lstlisting} 18 | >>> pow(2, 3) 19 | 8 20 | >>> pow(2, 3, 6) 21 | 2 22 | >>> pow(2, 5, 17) 23 | 15 24 | \end{lstlisting} 25 | \end{exampleblock} 26 | 27 | \small 28 | \begin{block} 29 | {\centering Built-in Functions: pow()} 30 | \centering \url{http://docs.python.org/2/library/functions.html\#pow} 31 | \end{block} 32 | \end{frame} 33 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/16.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{16. sorted() - parámetro 'key'} 5 | \footnotesize 6 | \begin{block}{} 7 | \centering 8 | Desde Python 2.4, tanto el método \structure{list.sort()} como la 9 | función \structure{sorted()} aceptan el parámetro \structure{key}, 10 | con el que se especifica la función que se ejecuta para cada 11 | elemento y a partir de cuyo resultado se ordena la secuencia. 12 | \end{block} 13 | 14 | \begin{exampleblock} 15 | {Ordenar una serie de números por su valor absoluto:} 16 | \begin{lstlisting} 17 | >>> nums = [-8, 3, 5, -1, 3] 18 | >>> sorted(nums, key=abs) 19 | [-1, 3, 3, 5, -8] 20 | \end{lstlisting} 21 | \end{exampleblock} 22 | 23 | \begin{exampleblock} 24 | {Una lista de cadenas lexicográficamente:} 25 | \begin{lstlisting} 26 | >>> gnu = ["GNU", "is", "Not", "Unix"] 27 | >>> sorted(gnu) 28 | ['GNU', 'Not', 'Unix', 'is'] 29 | \end{lstlisting} 30 | \end{exampleblock} 31 | \end{frame} 32 | 33 | \begin{frame}[fragile]{16. sorted() - parámetro 'key'} 34 | \begin{exampleblock} 35 | {Ahora por su longitud:} 36 | \begin{lstlisting} 37 | >>> sorted(gnu, key=len) 38 | ['is', 'GNU', 'Not', 'Unix'] 39 | \end{lstlisting} 40 | \end{exampleblock} 41 | 42 | \begin{alertblock}{} 43 | \centering 44 | Desde 2.2, las ordenaciones en Python son \structure{estables}: al 45 | tener 'GNU' y 'Not' la misma longitud, se mantiene el orden 46 | original. Esto permite ordenar en función de \structure{dos o más 47 | criterios}, en diferentes pasos. 48 | \end{alertblock} 49 | \end{frame} 50 | 51 | \begin{frame}[fragile]{16. sorted() - parámetro 'key'} 52 | \begin{block}{} 53 | \centering 54 | Podemos ordenar \structure{usando nuestras propias funciones} 55 | \end{block} 56 | 57 | \footnotesize 58 | \begin{exampleblock} 59 | {Ordenar por el número de vocales:} 60 | \begin{lstlisting} 61 | >>> def nvocales(palabra): 62 | ... contador = 0 63 | ... for letra in palabra: 64 | ... if letra.lower() in "aeiou": 65 | ... contador += 1 66 | ... return contador 67 | ... 68 | >>> lame = "LAME Ain't an MP3 Encoder".split() 69 | >>> sorted(lame, key=nvocales) 70 | ['MP3', 'an', 'LAME', "Ain't", 'Encoder'] 71 | \end{lstlisting} 72 | \end{exampleblock} 73 | \end{frame} 74 | 75 | \begin{frame}[fragile]{16. sorted() - parámetro 'key'} 76 | \begin{block}{} 77 | \centering 78 | O usando \structure{funciones anónimas} 79 | \end{block} 80 | 81 | \footnotesize 82 | \begin{exampleblock} 83 | {Ordenar por la parte compleja:} 84 | \begin{lstlisting} 85 | >>> nums = [7+9j, 4-5j, 3+2j] 86 | >>> sorted(nums, key=lambda x: x.imag) 87 | [(4-5j), (3+2j), (7+9j)] 88 | \end{lstlisting} 89 | \end{exampleblock} 90 | 91 | \begin{exampleblock} 92 | {Ordenar por el segundo elemento de la tupla:} 93 | \begin{lstlisting} 94 | >>> puntos = [(2, 3), (5, 1), (3, 4), (8, 2)] 95 | >>> sorted(puntos, key=lambda x: x[1]) 96 | [(5, 1), (8, 2), (2, 3), (3, 4)] 97 | \end{lstlisting} 98 | \end{exampleblock} 99 | 100 | \begin{block} 101 | {\centering Sorting Mini-HOW TO} 102 | \centering \url{http://wiki.python.org/moin/HowTo/Sorting/} 103 | \end{block} 104 | \end{frame} 105 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/18.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{18. Aplanando una lista con sum()} 5 | \begin{block}{} 6 | \centering \LARGE sum(iterable[, start]) 7 | \end{block} 8 | 9 | \small 10 | \begin{center} 11 | \centering 12 | La función sum() acepta, opcionalmente, un segundo argumento, 13 | \structure{start}, cuyo valor por defecto es cero, al cual se van 14 | sumando los elementos de \structure{iterable}. 15 | \end{center} 16 | 17 | \footnotesize 18 | \begin{exampleblock}{} 19 | \begin{lstlisting} 20 | >>> sum([1, 2, 3]) 21 | 6 22 | >>> sum([1, 2, 3], 10) 23 | 16 24 | >>> sum(range(1, 10)) 25 | 45 26 | >>> sum([100], -1) 27 | 99 28 | \end{lstlisting} 29 | \end{exampleblock} 30 | \end{frame} 31 | 32 | \begin{frame}[fragile]{18. Aplanando una lista con sum()} 33 | \begin{block}{} 34 | \centering 35 | Podemos usar una lista vacía, [], como \structure{start}, para aplanar 36 | una lista de listas. La función sum(), al 'sumarlas', lo que hará será 37 | \structure{concatenarlas} una detrás de otra. 38 | \end{block} 39 | 40 | \small 41 | \begin{exampleblock}{} 42 | \begin{lstlisting} 43 | >>> sum([[1, 2], [3], [4, 5], [6, 7, 8]], []) 44 | [1, 2, 3, 4, 5, 6, 7, 8] 45 | >>> sum([[4, 5], [6, 7]], range(4)) 46 | [0, 1, 2, 3, 4, 5, 6, 7] 47 | \end{lstlisting} 48 | \end{exampleblock} 49 | \end{frame} 50 | 51 | \begin{frame}[fragile]{18. Aplanando una lista con sum()} 52 | \begin{alertblock}{} 53 | \centering 54 | Es importante que \structure{start} sea una lista. De lo contrario, 55 | sum() intentará añadir cada una de las sublistas a un entero, cero. 56 | Y eso no se puede hacer. 57 | \end{alertblock} 58 | 59 | \scriptsize 60 | \begin{exampleblock}{} 61 | \begin{lstlisting} 62 | >>> sum([[4, 5], [6, 7]]) 63 | Traceback (most recent call last): 64 | File "", line 1, in 65 | TypeError: unsupported operand type(s) for +: 'int' and 'list' 66 | \end{lstlisting} 67 | \end{exampleblock} 68 | 69 | \small 70 | \begin{block} 71 | {\centering Stack Overflow - Flattening a list with sum():} 72 | \centering \url{http://stackoverflow.com/a/6632253/184363 } 73 | \end{block} 74 | \end{frame} 75 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/19.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{19. El operador ternario} 5 | \begin{center} 6 | El operator ternario (o condicional) nos permite escoger entre dos 7 | expresiones en \structure{función de una tercera}, la condición. 8 | \end{center} 9 | 10 | \begin{block} 11 | {\small 12 | En casi todos los lenguajes de programación tiene la misma forma:} 13 | \centering \LARGE test ? a : b 14 | \end{block} 15 | 16 | \begin{exampleblock}{Por ejemplo, en C:} 17 | \begin{lstlisting}[language=C] 18 | int nsecs = (counter > 5) ? 5 : 0; 19 | \end{lstlisting} 20 | \end{exampleblock} 21 | \end{frame} 22 | 23 | \begin{frame}[fragile]{19. El operador ternario} 24 | \begin{center} 25 | En Python se conocen como \structure{expresiones condicionales}, y 26 | existen desde la versión 2.5. Su sintaxis es: 27 | \end{center} 28 | 29 | \begin{block}{} 30 | \centering \LARGE a if test else b 31 | \end{block} 32 | 33 | \begin{exampleblock}{} 34 | \begin{lstlisting} 35 | >>> x = 2 36 | >>> "uno" if x == 1 else "otra cosa" 37 | 'otra cosa' 38 | \end{lstlisting} 39 | \end{exampleblock} 40 | \end{frame} 41 | 42 | \begin{frame}[fragile]{19. El operador ternario} 43 | \footnotesize 44 | \begin{exampleblock}{} 45 | \begin{lstlisting} 46 | >>> hora = 17 47 | >>> msg = ("Es la" if hora == 1 else "Son las") 48 | >>> msg + " {0}h".format(hora) 49 | 'Son las 17h' 50 | \end{lstlisting} 51 | \end{exampleblock} 52 | 53 | \begin{exampleblock} 54 | {Eleva al cuadrado si x es impar, divide entre dos de lo contrario:} 55 | \begin{lstlisting} 56 | >>> x = 13 57 | >>> y = x ** 2 if x % 2 else x / 2 58 | >>> y 59 | 169 60 | \end{lstlisting} 61 | \end{exampleblock} 62 | 63 | \small 64 | \begin{block} 65 | {\centering PEP 308: Conditional Expressions [2003]} 66 | \centering \url{http://www.python.org/dev/peps/pep-0308/} 67 | \end{block} 68 | \end{frame} 69 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/20.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile] 5 | {20. \large Incremento != 1 en el operador slice} 6 | \begin{block}{} 7 | \centering \LARGE x[start:end:step] 8 | \end{block} 9 | 10 | \small 11 | \begin{center} 12 | El tercer índice, opcional, del \structure{operador slice}, 13 | especifica el tamaño del paso --- cuánto avanzamos cada vez. 14 | Por defecto es uno, y por eso: 15 | \end{center} 16 | 17 | \begin{exampleblock} 18 | {Los tres primeros elementos} 19 | \begin{lstlisting} 20 | >>> x = range(1, 10) 21 | >>> x[:3] 22 | [0, 1, 2] 23 | \end{lstlisting} 24 | \end{exampleblock} 25 | \end{frame} 26 | 27 | \begin{frame}[fragile] 28 | {20. \large Incremento != 1 en el operador slice} 29 | \begin{exampleblock} 30 | {Los cuatro últimos} 31 | \begin{lstlisting} 32 | >>> x[-4:] 33 | [6, 7, 8, 9] 34 | \end{lstlisting} 35 | \end{exampleblock} 36 | 37 | \begin{exampleblock} 38 | {Del segundo al quinto} 39 | \begin{lstlisting} 40 | >>> x[1:5] 41 | [1, 2, 3, 4] 42 | \end{lstlisting} 43 | \end{exampleblock} 44 | \end{frame} 45 | 46 | \begin{frame}[fragile] 47 | {20. \large Incremento != 1 en el operador slice} 48 | \begin{block}{} 49 | \large 50 | \centering 51 | Podemos usar un paso \structure{distinto de uno} 52 | \end{block} 53 | 54 | \small 55 | \begin{exampleblock} 56 | {Elementos en posiciones pares...} 57 | \begin{lstlisting} 58 | >>> x[::2] 59 | [1, 3, 5, 7, 9] 60 | \end{lstlisting} 61 | \end{exampleblock} 62 | 63 | \begin{exampleblock} 64 | {... e impares} 65 | \begin{lstlisting} 66 | >>> x[1::2] 67 | [0, 2, 4, 6, 8] 68 | \end{lstlisting} 69 | \end{exampleblock} 70 | \end{frame} 71 | 72 | \begin{frame}[fragile] 73 | {20. \large Incremento != 1 en el operador slice} 74 | \begin{exampleblock} 75 | {Recorrer los primeros nueve elementos, de tres en tres} 76 | \begin{lstlisting} 77 | >>> x[:9:3] 78 | [0, 3, 6] 79 | \end{lstlisting} 80 | \end{exampleblock} 81 | 82 | \begin{alertblock}{} 83 | \small 84 | \centering 85 | Hacia adelante, empezamos a contar en \structure{cero}, terminamos 86 | en \structure{n-1} 87 | \end{alertblock} 88 | \end{frame} 89 | 90 | \begin{frame}[fragile] 91 | {20. \large Incremento != 1 en el operador slice} 92 | \begin{block}{} 93 | \centering 94 | Un paso negativo permite recorrer la lista \structure{hacia atrás} 95 | \end{block} 96 | 97 | \small 98 | \begin{exampleblock} 99 | {Invierte la lista} 100 | \begin{lstlisting} 101 | >>> x[::-1] 102 | [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 103 | \end{lstlisting} 104 | \end{exampleblock} 105 | 106 | \begin{exampleblock} 107 | {Recorre la lista hacia atrás, de dos en dos} 108 | \begin{lstlisting} 109 | >>> x[::-2] 110 | [9, 7, 5, 3, 1] 111 | \end{lstlisting} 112 | \end{exampleblock} 113 | \end{frame} 114 | 115 | \begin{frame}[fragile] 116 | {20. \large Incremento != 1 en el operador slice} 117 | \begin{exampleblock} 118 | {Del último hasta el tercero, no inclusive, hacia atrás} 119 | \begin{lstlisting} 120 | >>> x[:2:-1] 121 | [9, 8, 7, 6, 5, 4, 3] 122 | \end{lstlisting} 123 | \end{exampleblock} 124 | 125 | \begin{alertblock}{} 126 | \small 127 | \centering 128 | Hacia atrás, empezamos a contar en \structure{-1}, terminamos 129 | en \structure{-len} 130 | \end{alertblock} 131 | \end{frame} 132 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/21.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{21. La variable \_} 5 | \begin{alertblock}{} 6 | \small 7 | \centering 8 | En el modo interactivo (Python shell), la variable \structure{\_} 9 | siempre contiene el valor del \structure{último} \emph{statement} 10 | ejecutado. Es muy útil si necesitamos \structure{reusar} el último 11 | valor que hemos calculado y olvidamos almacenarlo en una variable: 12 | \end{alertblock} 13 | 14 | \footnotesize 15 | \begin{exampleblock}{} 16 | \begin{lstlisting} 17 | >>> 3 * 4 18 | 12 19 | >>> _ + 1 20 | 13 21 | >>> _ ** 2 22 | 169 23 | >>> range(10) 24 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 25 | >>> _[-1] 26 | 9 27 | \end{lstlisting} 28 | \end{exampleblock} 29 | \end{frame} 30 | 31 | \begin{frame}[fragile]{21. La variable \_} 32 | \begin{block}{} 33 | \small 34 | \centering 35 | En modo no-interactivo (un script en Python cualquiera), 36 | \structure{\_} es un nombre más de variable. Por convención, suele 37 | usarse como nombre de variable para indicar que es 38 | \structure{desechable} (\emph{throwaway variable}), cuando 39 | necesitamos una pero \structure{no llegamos a usarla}. 40 | \end{block} 41 | 42 | \footnotesize 43 | \begin{exampleblock}{} 44 | \begin{lstlisting} 45 | >>> for _ in range(10): 46 | ... print "¡Hola, mundo!" 47 | \end{lstlisting} 48 | \end{exampleblock} 49 | 50 | 51 | \begin{exampleblock}{} 52 | \begin{lstlisting} 53 | >>> import os.path 54 | >>> path = "curriculum.tex" 55 | >>> _, ext = os.path.splitext(path) 56 | >>> ext 57 | '.tex' 58 | \end{lstlisting} 59 | \end{exampleblock} 60 | \end{frame} 61 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/22.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{22. \large Funciones lambda, y qué opina GvR} 5 | \small 6 | \begin{center} 7 | Antes hemos usado \structure{funciones lambda} (o anónimas) para 8 | definir sobre la marcha funciones sencillas que sólo necesitábamos 9 | una vez. Recordemos: 10 | \end{center} 11 | 12 | \footnotesize 13 | \begin{exampleblock} 14 | {Ordenar por la parte compleja:} 15 | \begin{lstlisting} 16 | >>> nums = [7+9j, 4-5j, 3+2j] 17 | >>> sorted(nums, key=lambda x: x.imag) 18 | [(4-5j), (3+2j), (7+9j)] 19 | \end{lstlisting} 20 | \end{exampleblock} 21 | 22 | \small 23 | \begin{block}{} 24 | \centering 25 | Las funciones lambda son muy útiles y cómodas en algunas 26 | ocasiones. Provienen del mundo de la \structure{programación 27 | funcional}, al igual que las funciones de orden superior 28 | \structure{map()}, \structure{filter()} y \structure{reduce()}. 29 | \end{block} 30 | \end{frame} 31 | 32 | \begin{frame}[fragile]{22. \large Funciones lambda, y qué opina GvR} 33 | \begin{alertblock}{} 34 | \large 35 | \centering 36 | Pero a Guido van Rossum no le gustan. 37 | \end{alertblock} 38 | 39 | \small 40 | \begin{center} 41 | Nunca le convencieron y, de hecho, estuvieron a punto de desaparecer en Py3K. 42 | \end{center} 43 | 44 | \footnotesize 45 | \begin{center} 46 | El nombre de lambda puede dar lugar a confusión, ya que su 47 | semántica \structure{no es la misma} que en otros lenguajes. La 48 | idea de \structure{lambda} era sólo la de servir de herramienta 49 | sintática para definir funciones anónimas. El problema es que 50 | nadie ha sido capaz todavía de encontrar una forma mejor forma 51 | esto, por lo que \structure{lambda} sigue entre nosotros. 52 | \end{center} 53 | 54 | \begin{block} 55 | {\centering Origins of Python's "Functional" Features:} 56 | \centering \url{http://python-history.blogspot.com.es/2009/04/origins-of-pythons-functional-features.html} 57 | \end{block} 58 | \end{frame} 59 | 60 | \begin{frame}[fragile]{22. \large Funciones lambda, y qué opina GvR} 61 | \small 62 | \begin{block}{} 63 | \centering 64 | Así que \structure{lambda} sigue existiendo, pero lo Pythónico es 65 | usar el módulo \structure{operator}. Más legible, más claro, más 66 | explícito. 67 | \end{block} 68 | 69 | \footnotesize 70 | \begin{exampleblock} 71 | {Ordenando de nuevo por la parte compleja...} 72 | \begin{lstlisting} 73 | >>> import operator 74 | >>> nums = [7+9j, 4-5j, 3+2j] 75 | >>> sorted(nums, key=operator.attrgetter('imag')) 76 | [(4-5j), (3+2j), (7+9j)] 77 | \end{lstlisting} 78 | \end{exampleblock} 79 | 80 | \begin{exampleblock} 81 | {... y por el segundo elemento de la tupla:} 82 | \begin{lstlisting} 83 | >>> import operator 84 | >>> puntos = [(2, 3), (5, 1), (3, 4), (8, 2)] 85 | >>> sorted(puntos, key=operator.itemgetter(1)) 86 | [(5, 1), (8, 2), (2, 3), (3, 4)] 87 | \end{lstlisting} 88 | \end{exampleblock} 89 | \end{frame} 90 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/23.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 5 | \begin{exampleblock}{} 6 | \small 7 | \begin{lstlisting} 8 | >>> def inserta_uno(valores=[]): 9 | ... valores.append(1) 10 | ... return valores 11 | ... 12 | >>> inserta_uno(range(3)) 13 | [0, 1, 2, 1] 14 | >>> inserta_uno() 15 | [1] 16 | >>> inserta_uno() 17 | [1, 1] 18 | >>> inserta_uno() 19 | [1, 1, 1] 20 | \end{lstlisting} 21 | \end{exampleblock} 22 | \end{frame} 23 | 24 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 25 | \begin{figure} 26 | \centering 27 | \includegraphics[height=6cm]{pics/omg-face.jpg} 28 | \end{figure} 29 | \end{frame} 30 | 31 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 32 | \begin{block}{} 33 | \centering 34 | \small 35 | El motivo por el que esto ocurre es que las funciones en Python 36 | son objetos de primera clase, no sólo un trozo más de código: 37 | \structure{se evalúan cuando son definidas}, incluyendo parámetros 38 | por defecto, y por tanto su estado puede cambiar de una vez a 39 | otra. 40 | \end{block} 41 | 42 | \begin{alertblock}{} 43 | \centering 44 | Es decir, que los parámetros por defecto se evalúan sólo 45 | \structure{una} vez, en el momento en el que \structure{la función 46 | se define}. 47 | \end{alertblock} 48 | \end{frame} 49 | 50 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 51 | \begin{block}{} 52 | \centering 53 | La solución es usar un \structure{parámetro de sustitución}, en 54 | lugar de modificar directamente el valor por defecto. 55 | \end{block} 56 | 57 | \begin{exampleblock}{} 58 | \footnotesize 59 | \begin{lstlisting} 60 | >>> def inserta_uno(valores=None): 61 | ... if valores is None: 62 | ... valores = [] 63 | ... valores.append(1) 64 | ... return valores 65 | ... 66 | >>> inserta_uno() 67 | [1] 68 | >>> inserta_uno() 69 | [1] 70 | >>> inserta_uno() 71 | [1] 72 | \end{lstlisting} 73 | \end{exampleblock} 74 | \end{frame} 75 | 76 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 77 | \begin{alertblock} 78 | \large 79 | \centering 80 | ¿Y entonces esto? 81 | \end{alertblock} 82 | 83 | \begin{exampleblock}{} 84 | \small 85 | \begin{lstlisting} 86 | >>> def suma(numeros, inicio=0): 87 | ... for x in numeros: 88 | ... inicio += x 89 | ... return inicio 90 | ... 91 | >>> suma([1, 2]) 92 | 3 93 | >>> suma([3, 4]) 94 | 7 95 | >>> suma([1, 2, 3]) 96 | 6 97 | \end{lstlisting} 98 | \end{exampleblock} 99 | \end{frame} 100 | 101 | \begin{frame}[fragile]{23. Parámetros por defecto mutables} 102 | \begin{block}{} 103 | \centering 104 | La razón es que, a diferencia de las listas, los enteros en Python 105 | son \structure{inmutables}, por lo que no pueden modificarse de 106 | una llamada a otra. Por tanto, \structure{inicio} siempre es cero 107 | cuando llamamos a la función. 108 | \end{block} 109 | 110 | \small 111 | \begin{block} 112 | {\centering Call By Object} 113 | \centering \url{http://effbot.org/zone/call-by-object.htm} 114 | \end{block} 115 | 116 | \begin{block} 117 | {\centering Default Parameter Values in Python} 118 | \centering \url{http://effbot.org/zone/default-values.htm} 119 | \end{block} 120 | \end{frame} 121 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/26.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{26. try-except-else-finally} 5 | \begin{alertblock}{} 6 | \centering 7 | La construcción \structure{try-except-finally} admite también la 8 | cláusula \structure{else}: este bloque de código se ejecuta sólo 9 | si no se ha lanzado ninguna excepción. 10 | \end{alertblock} 11 | 12 | \begin{center} 13 | \small 14 | Esto nos permite minimizar el código que escribimos dentro de la 15 | cláusula \structure{try}, reduciendo el riesgo de que 16 | \structure{except} capture una excepción que realmente no 17 | queríamos proteger con el \structure{try}. 18 | \end{center} 19 | \end{frame} 20 | 21 | \begin{frame}[fragile]{26. try-except-else-finally} 22 | \begin{exampleblock} 23 | {\footnotesize 24 | Descarga presentación, descomprime, actualiza log} 25 | \tiny 26 | \begin{lstlisting}[escapechar=!] 27 | import os 28 | import urllib 29 | import zipfile 30 | 31 | url = "http://github.com/vterron/PyConES-2013/archive/master.zip" 32 | path = "charla-pycon.zip" 33 | 34 | try: 35 | urllib.urlretrieve(url, path) 36 | myzip = zipfile.ZipFile(path) 37 | myzip.extractall() # puede lanzar !\color{red}{IOError}! 38 | 39 | # Tambien puede lanzar !\color{red}{IOError}! 40 | with open("descargas-log", "at") as fd: 41 | fd.write("{0}\n".format(path)) 42 | 43 | except !\color{red}{IOError}!: 44 | print "He capturado IOError!" 45 | 46 | finally: 47 | os.unlink(path) 48 | \end{lstlisting} 49 | \end{exampleblock} 50 | 51 | \small 52 | \begin{alertblock}{} 53 | \centering 54 | ¿Cuál de los dos \structure{IOError} he capturado? 55 | \structure{No lo sabemos} 56 | \end{alertblock} 57 | \end{frame} 58 | 59 | \begin{frame}[fragile]{26. try-except-else-finally} 60 | 61 | \begin{exampleblock} 62 | {\footnotesize 63 | Por supuesto, podríamos evitar este problema anidando try-elses:} 64 | \tiny 65 | \begin{lstlisting} 66 | try: 67 | urllib.urlretrieve(url, path) 68 | myzip = zipfile.ZipFile(path) 69 | try: 70 | myzip.extractall() 71 | try: 72 | with open("descargas-log", "at") as fd: 73 | fd.write("{0}\n".format(path)) 74 | except IOError: 75 | print "Error escribiendo fichero" 76 | 77 | except IOError: 78 | print "Error descomprimiendo fichero ZIP" 79 | 80 | finally: 81 | os.unlink(path) 82 | \end{lstlisting} 83 | \end{exampleblock} 84 | 85 | \small 86 | \begin{alertblock}{} 87 | \centering 88 | Pero, como dice el Zen de Python, "\emph{Flat is better than nested}" 89 | \end{alertblock} 90 | \end{frame} 91 | 92 | \begin{frame}[fragile]{26. try-except-else-finally} 93 | \begin{block}{} 94 | \centering 95 | Utilizando la cláusula \structure{else} basta con: 96 | \end{block} 97 | 98 | \begin{exampleblock}{} 99 | \footnotesize 100 | \begin{lstlisting}[escapechar=!] 101 | try: 102 | urllib.urlretrieve(url, path) 103 | myzip = zipfile.ZipFile(path) 104 | myzip.extractall() 105 | except IOError: 106 | print "Error descomprimiendo fichero ZIP" 107 | !\color{red}{else:}! 108 | with open("descargas-log", "at") as fd: 109 | fd.write("{0}\n".format(path)) 110 | finally: 111 | os.unlink(path) 112 | \end{lstlisting} 113 | \end{exampleblock} 114 | \end{frame} 115 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/27.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{27. Relanzamiento de excepciones} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | \structure{raise} a secas, dentro del bloque de la cláusula 9 | \structure{except}, relanza la excepción con la traza (traceback) 10 | original intanta. Esto es muy útil si queremos hacer algo más 11 | antes de lanzar la excepción. 12 | \end{block} 13 | 14 | \begin{exampleblock}{} 15 | \scriptsize 16 | \begin{lstlisting}[escapechar=!] 17 | >>> x = 1 18 | >>> y = 0 19 | >>> try: 20 | ... z = x / y 21 | ... except ZeroDivisionError: 22 | ... print "Imposible dividir. Abortando..." 23 | ... !\color{blue}{raise}! 24 | ... 25 | Imposible dividir. Abortando... 26 | Traceback (most recent call last): 27 | File "", line 2, in 28 | ZeroDivisionError: integer division or modulo by zero 29 | \end{lstlisting} 30 | \end{exampleblock} 31 | \end{frame} 32 | 33 | \begin{frame}[fragile]{27. Relanzamiento de excepciones} 34 | \footnotesize 35 | \begin{alertblock}{} 36 | \centering 37 | Pero, claro, raise relanza la \structure{última} excepción. En 38 | caso de que dentro del \structure{except} exista la posibilidad de 39 | que se lance una segunda excepción, podemos almacenarla para 40 | asegurarnos de que no la perdemos. 41 | \end{alertblock} 42 | 43 | \begin{exampleblock} 44 | {En Python 3000:} 45 | \tiny 46 | \begin{lstlisting}[escapechar=!] 47 | import os 48 | 49 | try: 50 | path = "resultado.txt" 51 | with open(path, "wt") as fd: 52 | resultado = 1 / 0 53 | fd.write(str(resultado)) 54 | 55 | except BaseException !\color{blue}{as e}!: 56 | 57 | try: 58 | os.unlink(path) 59 | except Exception as sub_e: 60 | print("Ha ocurrido otro error:") 61 | print(sub_e) 62 | 63 | !\color{blue}{raise e}! 64 | \end{lstlisting} 65 | \end{exampleblock} 66 | \end{frame} 67 | 68 | \begin{frame}[fragile]{27. Relanzamiento de excepciones} 69 | \footnotesize 70 | \begin{exampleblock} 71 | {Esto produce:} 72 | \begin{lstlisting}[escapechar=!] 73 | >>> python3.1 relanza-excepcion.py 74 | Ha ocurrido otro error: 75 | [Errno 13] Permission denied: '/root/.bashrc' 76 | Traceback (most recent call last): 77 | File "relanza.py", line 18, in 78 | raise e 79 | File "relanza.py", line 8, in 80 | resultado = 1 / 0 81 | ZeroDivisionError: int division or modulo by zero 82 | \end{lstlisting} 83 | \end{exampleblock} 84 | \end{frame} 85 | 86 | \begin{frame}[fragile]{27. Relanzamiento de excepciones} 87 | \small 88 | \begin{block}{} 89 | \centering 90 | En Python 2 también podemos usar la notación except 91 | \structure{Exception, e} (sin los paréntesis), pero desde 2.6+ la 92 | keyword \structure{as} permite que nuestro código sea mucho menos 93 | ambiguo. 94 | \end{block} 95 | 96 | \begin{block} 97 | {\centering Python try...except comma vs 'as' in except} 98 | \centering \url{http://stackoverflow.com/a/2535770/184363} 99 | \end{block} 100 | 101 | \begin{block} 102 | {\centering PEP 3110: Catching Exceptions in Python 3000:} 103 | \centering \url{http://www.python.org/dev/peps/pep-3110/} 104 | \end{block} 105 | \end{frame} 106 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/28.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}{28. \_\_str\_\_() vs \_\_repr\_\_()} 5 | 6 | \footnotesize 7 | \begin{alertblock} 8 | {\centering 9 | \small 10 | El objetivo de \_\_repr\_\_() es ser inequívoco. 11 | } 12 | \centering 13 | 14 | {Este método, ejecutado vía \structure{repr()}, devuelve una 15 | cadena de texto con la \structure{representación única del 16 | objeto}. Se usa sobre todo para depurar errores, por lo que la 17 | idea es que incluya toda la información que necesitamos --- por 18 | ejemplo, intentando entender qué ha fallado analizando unos 19 | logs. } 20 | \end{alertblock} 21 | 22 | \begin{block} 23 | {\centering 24 | \small 25 | El objetivo de \_\_str\_\_() es ser legible. 26 | } 27 | \centering 28 | {\footnotesize 29 | La cadena que devuelve \structure{str()} no tiene otro fin que 30 | el de ser fácil de comprender por \structure{humanos}: cualquier 31 | cosa que aumente la legibilidad, como eliminar decimales 32 | inútiles o información poco importante, es aceptable. 33 | } 34 | \end{block} 35 | \end{frame} 36 | 37 | \begin{frame}[fragile]{28. \_\_str\_\_() vs \_\_repr\_\_()} 38 | \footnotesize 39 | \begin{exampleblock} 40 | {El módulo datetime nos proporciona un buen ejemplo:} 41 | \begin{lstlisting} 42 | >>> import datetime 43 | >>> today = datetime.datetime.now() 44 | >>> str(today) 45 | '2013-11-20 13:51:53.006588' 46 | >>> repr(today) 47 | 'datetime.datetime(2013, 11, 20, 13, 51, 53, 6588)' 48 | \end{lstlisting} 49 | \end{exampleblock} 50 | \end{frame} 51 | 52 | \begin{frame}[fragile]{28. \_\_str\_\_() vs \_\_repr\_\_()} 53 | \small 54 | \begin{block}{} 55 | \centering 56 | Idealmente, la cadena devuelta por \structure{\_\_repr\_\_()} 57 | debería ser aquella que, pasada a \structure{eval()}, devuelve el 58 | mismo objeto. Al fin y al cabo, si \structure{eval()} es capaz de 59 | reconstruir el objeto a partir de ella, esto garantiza que 60 | contiene \structure{toda} la infomación necesaria: 61 | \end{block} 62 | 63 | \footnotesize 64 | \begin{exampleblock} {} 65 | \begin{lstlisting} 66 | >>> today = datetime.datetime.now() 67 | >>> repr(today) 68 | 'datetime.datetime(2013, 11, 20, 13, 54, 33, 934577)' 69 | >>> today == eval(repr(today)) 70 | True 71 | \end{lstlisting} 72 | \end{exampleblock} 73 | \end{frame} 74 | 75 | \begin{frame}{28. \_\_str\_\_() vs \_\_repr\_\_()} 76 | \begin{alertblock}{} 77 | \centering 78 | Por cierto, ¡usar \structure{eval(repr(obj))} para serializar 79 | objetos no es buena idea! Es poco eficiente y, mucho peor, 80 | peligroso. Usa \structure{pickle} mejor. 81 | \end{alertblock} 82 | 83 | \small 84 | \begin{block} 85 | {\centering Eval really is dangerous:} 86 | \centering \url{http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html} 87 | \end{block} 88 | \end{frame} 89 | 90 | \begin{frame}{28. \_\_str\_\_() vs \_\_repr\_\_()} 91 | \small 92 | \begin{alertblock}{} 93 | \centering 94 | \_\_repr\_\_() es para \structure{desarrolladores}, 95 | \_\_str\_\_() para \structure{usuarios}. 96 | \end{alertblock} 97 | 98 | \begin{block}{} 99 | \centering 100 | En caso de que nuestra clase defina \_\_repr\_\_() pero no 101 | \_\_str\_\_(), la llamada a \structure{str() también devuelve 102 | repr()}. Así que el único que de verdad tenemos que 103 | implementar es \_\_repr\_\_(). 104 | \end{block} 105 | 106 | \begin{block} 107 | {\centering Difference between \_\_str\_\_ and \_\_repr\_\_ in Python:} 108 | \centering \url{http://stackoverflow.com/q/1436703/184363} 109 | \end{block} 110 | \end{frame} 111 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/30.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}{30. \{\} y dict()} 5 | \begin{center} 6 | \centering 7 | \small 8 | Habitualmente los \structure{diccionarios} se contruyen usando \structure{{}} 9 | \end{center} 10 | 11 | \begin{block}{} 12 | \Large 13 | \centering {'uno': 1, 'dos': 2, 'tres': 3} 14 | \end{block} 15 | 16 | \vspace{0.5cm} 17 | 18 | \begin{center}{} 19 | \centering 20 | \small 21 | También podemos hacerlo, sin embargo, utilizando 22 | \structure{dict()}. Esto tiene la ventaja de que podemos definir 23 | los elementos del diccionario como \structure{argumentos 24 | nombrados} --- esto nos ahorra tener que poner comillas 25 | alrededor de las claves que sean cadenas de texto: 26 | \end{center} 27 | 28 | \begin{block}{} 29 | \Large 30 | \centering dict(uno = 1, dos = 2, tres = 3) 31 | \end{block} 32 | \end{frame} 33 | 34 | \begin{frame}[fragile]{30. \{\} y dict()} 35 | \small 36 | \begin{block}{} 37 | \centering 38 | Una \structure{limitación de dict()} es que las claves de nuestro 39 | diccionario sólo pueden ser identificadores (nombres de variable) 40 | \structure{válidos} en Python. Por el contrario, \structure{\{\}} 41 | admite cualquier identificador. 42 | \end{block} 43 | 44 | \footnotesize 45 | \begin{exampleblock} 46 | {Esto es perfectamente legal} 47 | \begin{lstlisting} 48 | >>> d = {1 : "uno", 2 : "dos", 3 : "tres"} 49 | >>> d[1] 50 | 'uno' 51 | \end{lstlisting} 52 | \end{exampleblock} 53 | 54 | \begin{exampleblock} 55 | {Pero un entero no es un nombre de variable válido:} 56 | \begin{lstlisting} 57 | >>> dict(1 = "uno", 2 = "dos", 3 = "tres") 58 | File "", line 1 59 | SyntaxError: keyword can't be an expression 60 | \end{lstlisting} 61 | \end{exampleblock} 62 | \end{frame} 63 | 64 | \begin{frame}[fragile]{30. \{\} y dict()} 65 | \begin{alertblock}{} 66 | \centering 67 | Esto es, en esencia, \structure{una cuestión de estilo} -- hay 68 | quien lo considera más cómodo y legible, pero dict() también tiene 69 | sus detractores. 70 | \end{alertblock} 71 | 72 | \vspace{0.5cm} 73 | 74 | \footnotesize 75 | \begin{center} 76 | \centering 77 | Doug Hellmann, por ejemplo, ha cuantificado que es seis veces más 78 | lento que \{\}, y que consume más memoria. 79 | \end{center} 80 | 81 | \footnotesize 82 | \begin{block} 83 | {\centering The Performance Impact of Using dict() Instead of \{\} in CPython 2.7} 84 | \centering 85 | \url{http://doughellmann.com/2012/11/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2.html} 86 | \end{block} 87 | \end{frame} 88 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/31.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{31. dict.\_\_missing\_\_()} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | En las \structure{subclases} de dict que definen 9 | \structure{\_\_missing\_\_()}, el acceso a claves que no estén 10 | presentes en el diccionario devuelve lo que este método devuelva. 11 | \end{block} 12 | 13 | \scriptsize 14 | \begin{exampleblock}{} 15 | % Escape triple quotes; otherwise string is italicized 16 | \begin{lstlisting}[escapechar=!] 17 | class MyDict(dict): 18 | !"""! Diccionario que devuelve -1 si la clave no existe !"""! 19 | 20 | def __missing__(self, key): 21 | print "'{0}' no encontrado".format(key) 22 | return -1 23 | 24 | >>> d = MyDict() 25 | >>> d[1] = 3 26 | >>> d[1] 27 | 3 28 | >>> d[5] 29 | '5' no encontrado 30 | -1 31 | \end{lstlisting} 32 | \end{exampleblock} 33 | \end{frame} 34 | 35 | \begin{frame}[fragile]{31. dict.\_\_missing\_\_()} 36 | \small 37 | \begin{alertblock}{} 38 | \centering 39 | \_\_missing\_\_() \structure{no puede ser una variable} -- ha de ser un 40 | método, que recibirá como argumento la clave que no se ha 41 | encontrado. 42 | \end{alertblock} 43 | 44 | \scriptsize 45 | \begin{exampleblock} 46 | {\footnotesize Algo que no va a funcionar:} 47 | \begin{lstlisting}[escapechar=!] 48 | class MyDict(dict): 49 | !"""! Diccionario que devuelve -1 si la clave no existe !"""! 50 | 51 | __missing__ = -1 52 | 53 | >>> d = MyDict() 54 | >>> d[7] 55 | Traceback (most recent call last): 56 | File "", line 1, in 57 | TypeError: 'int' object is not callable 58 | \end{lstlisting} 59 | \end{exampleblock} 60 | \end{frame} 61 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/32.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{32. collections.defaultdict} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | Normalmente es mucho mejor, no obstante, usar 9 | \structure{defaultdict}: se comporta como un diccionario a todos 10 | con los efectos, con la única diferencia de que al crearlo 11 | especificamos \structure{el valor que tendrán por defecto} las 12 | claves a las que accedamos que no existan. 13 | \end{block} 14 | 15 | \footnotesize 16 | \begin{exampleblock} 17 | {Para implementar un contador, en vez de hacer esto...} 18 | \begin{lstlisting} 19 | mydict = dict() 20 | for letra in palabra: 21 | if letra in mydict: 22 | mydict[letra] += 1 23 | else: 24 | mydict[letra] = 1 25 | \end{lstlisting} 26 | \end{exampleblock} 27 | \end{frame} 28 | 29 | \begin{frame}[fragile]{32. collections.defaultdict} 30 | \footnotesize 31 | \begin{exampleblock} 32 | {...o incluso esto...} 33 | \begin{lstlisting} 34 | mydict = dict() 35 | for letra in palabra: 36 | try: 37 | mydict[letra] += 1 38 | except KeyError: 39 | mydict[letra] = 1 40 | \end{lstlisting} 41 | \end{exampleblock} 42 | \end{frame} 43 | 44 | \begin{frame}[fragile]{32. collections.defaultdict} 45 | \footnotesize 46 | \begin{exampleblock} 47 | {Mucho mejor así:} 48 | \begin{lstlisting} 49 | import collections 50 | mydict = collections.defaultdict(int) 51 | for letra in palabra: 52 | mydict[letra] += 1 53 | \end{lstlisting} 54 | \end{exampleblock} 55 | 56 | \small 57 | \begin{alertblock}{} 58 | \centering 59 | ¡Pero esto es sólo un ejemplo! En código real \structure{nunca} 60 | implementéis un contador así! Lo tenéis ya hecho por gente mucho 61 | más capaz que nosotros, y disponible desde Python 2.7, en este 62 | mismo módulo: 63 | \structure{collections.Counter}. 64 | \end{alertblock} 65 | \end{frame} 66 | 67 | \begin{frame}[fragile]{32. collections.defaultdict} 68 | \small 69 | \begin{exampleblock} 70 | {Valor por defecto: []} 71 | \begin{lstlisting} 72 | collections.defaultdict(list) 73 | \end{lstlisting} 74 | \end{exampleblock} 75 | 76 | \small 77 | \begin{exampleblock} 78 | {Valor por defecto: set()} 79 | \begin{lstlisting} 80 | collections.defaultdict(set) 81 | \end{lstlisting} 82 | \end{exampleblock} 83 | 84 | \begin{exampleblock} 85 | {Valor por defecto: \{\}} 86 | \begin{lstlisting} 87 | d = collections.defaultdict(dict) 88 | d[0][3] = 3.43 89 | d[1][5] = 1.87 90 | \end{lstlisting} 91 | \end{exampleblock} 92 | \end{frame} 93 | 94 | \begin{frame}[fragile]{32. collections.defaultdict} 95 | \small 96 | \begin{block}{} 97 | \centering 98 | Para usar valores por defecto \structure{diferentes de cero o 99 | vacíos}, tenemos que tener presente que lo que 100 | defaultdict.\_\_init\_\_() recibe es \structure{una función} que 101 | acepta cero argumentos, que es la que se ejecuta cada vez que la 102 | clave no se encuentra. 103 | \end{block} 104 | 105 | \begin{exampleblock} 106 | {Valor por defecto: -7} 107 | \begin{lstlisting} 108 | collections.defaultdict(lambda: -7) 109 | \end{lstlisting} 110 | \end{exampleblock} 111 | 112 | \begin{exampleblock} 113 | {Valor por defecto: números [0, 7]} 114 | \begin{lstlisting} 115 | collections.defaultdict(lambda: range(8)) 116 | \end{lstlisting} 117 | \end{exampleblock} 118 | \end{frame} 119 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/33.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{33. collections.namedtuple} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | Devuelve un tipo de dato, subclase de \structure{tuple}, que 9 | podemos usar para crear tuplas que además nos permiten acceder 10 | también por atributos. Con \structure{namedtuple} estamos 11 | definiendo nuestra propia clase en una línea de código -- no deja 12 | de estar bien, aunque sean clases sencillas. 13 | \end{block} 14 | 15 | \scriptsize 16 | \begin{exampleblock} 17 | {\footnotesize La clase Punto(x, y, z)} 18 | \begin{lstlisting} 19 | >>> Punto = collections.namedtuple('Punto', ['x', 'y', 'z']) 20 | >>> Punto.__mro__ 21 | (, , 22 | \end{lstlisting} 23 | \end{exampleblock} 24 | \end{frame} 25 | 26 | \begin{frame}[fragile]{33. collections.namedtuple} 27 | \small 28 | \begin{exampleblock} 29 | {Y ahora usándola:} 30 | \begin{lstlisting} 31 | >>> dest = Punto(1, 4, 3) 32 | >>> dest.x 33 | 1 34 | >>> dest.y 35 | 4 36 | >>> dest[2] 37 | 3 38 | \end{lstlisting} 39 | \end{exampleblock} 40 | 41 | \begin{block} 42 | {\centering Understanding Python's iterator, iterable, and iteration protocols} 43 | \centering \url{http://stackoverflow.com/q/9884132/184363} 44 | \end{block} 45 | \end{frame} 46 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/34.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{34. itertools.chain()} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | La función \structure{chain()}, del módulo \structure{itertools}, 9 | crea un \structure{iterador} que devuelve, uno a uno, elementos de 10 | cada uno de los iterables que recibe, recorriéndolos todos. 11 | \end{block} 12 | 13 | \footnotesize 14 | \begin{exampleblock}{} 15 | \begin{lstlisting} 16 | >>> import itertools 17 | >>> x = [1, 2, 3] 18 | >>> y = [8, 9, 10] 19 | >>> for numero in itertools.chain(x, y): 20 | ... print numero 21 | ... 22 | 1 23 | 2 24 | 3 25 | 8 26 | 9 27 | 10 28 | \end{lstlisting} 29 | \end{exampleblock} 30 | \end{frame} 31 | 32 | \begin{frame}[fragile]{34. itertools.chain()} 33 | \scriptsize 34 | \begin{exampleblock} 35 | {\footnotesize 36 | Aplanar una lista de listas, como hicimos antes:} 37 | \begin{lstlisting} 38 | >>> it = itertools.chain([1, 2], [3], [4, 5], [6, 7, 8]) 39 | >>> it 40 | 41 | >>> list(it) 42 | [1, 2, 3, 4, 5, 6, 7, 8] 43 | >>> list(it) 44 | [] 45 | \end{lstlisting} 46 | \end{exampleblock} 47 | 48 | \begin{exampleblock} 49 | {\footnotesize 50 | Utilizando * para desempaquetar las sublistas:} 51 | \begin{lstlisting} 52 | >>> sublistas = [[4, 5], [6, 7]] 53 | >>> list(itertools.chain(*sublistas)) 54 | [4, 5, 6, 7] 55 | \end{lstlisting} 56 | \end{exampleblock} 57 | \end{frame} 58 | 59 | \begin{frame}[fragile]{34. itertools.chain()} 60 | \small 61 | \begin{alertblock}{} 62 | \centering 63 | Pero \structure{chain()} acepta mucho más que listas: le podemos pasar 64 | \structure{cualquier cosa sobre la que se pueda iterar}. Esto incluye 65 | generadores, conjuntos, diccionarios y cualquier objeto cuyos 66 | elementos podemos recorrer de uno en uno. 67 | \end{alertblock} 68 | 69 | \scriptsize 70 | \begin{exampleblock} 71 | {Dos conjuntos:} 72 | \begin{lstlisting} 73 | >>> s1 = set([1, 2, 3]) 74 | >>> s2 = set([6, 5, 4]) 75 | >>> list(itertools.chain(s1, s2)) 76 | [1, 2, 3, 4, 5, 6] 77 | \end{lstlisting} 78 | \end{exampleblock} 79 | 80 | \begin{exampleblock} 81 | {Diccionaro (claves) y conjunto:} 82 | \begin{lstlisting} 83 | >>> d1 = {1 : "uno", 2 : "dos"} 84 | >>> s1 = set(["tres", "cuatro"]) 85 | >>> list(itertools.chain(d1, d2)) 86 | [1, 2, 'cuatro', 'tres'] 87 | \end{lstlisting} 88 | \end{exampleblock} 89 | \end{frame} 90 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/35.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{35. functools.partial()} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | En el módulo \structure{functools}, la función 9 | \structure{partial()} nos permite \emph{congelar} otra función, 10 | \structure{fijándole argumentos} de forma que podamos llamarla de 11 | forma más sencilla y corta. 12 | \end{block} 13 | 14 | \begin{exampleblock}{} 15 | \begin{lstlisting} 16 | >>> import functools 17 | >>> eleva_dos = functools.partial(pow, 2) 18 | \end{lstlisting} 19 | \end{exampleblock} 20 | 21 | \begin{exampleblock} 22 | {Y ahora usándola:} 23 | \begin{lstlisting} 24 | >>> eleva_dos(3) 25 | 8 26 | >>> eleva_dos(10) 27 | 1024 28 | \end{lstlisting} 29 | \end{exampleblock} 30 | \end{frame} 31 | 32 | \begin{frame}[fragile]{35. functools.partial()} 33 | \small 34 | \begin{alertblock}{} 35 | \centering 36 | Es importante tener presente que los argumentos que nosotros le 37 | pasamos a la función \emph{congelada} se añaden 38 | \structure{después} de los que hemos definido en 39 | \structure{partial()}. Es necesario dar un rodeo si queremos crear 40 | funciones parciales que añadan los argumentos por el comienzo -- 41 | por ejemplo, para devolver \structure{pow(x, 3)}. 42 | \end{alertblock} 43 | 44 | \begin{block} 45 | {\centering Python: Why is functools.partial necessary?} 46 | \centering \url{http://stackoverflow.com/a/3252425/184363} 47 | \end{block} 48 | 49 | \begin{block} 50 | {\centering implementing functools.partial that prepends additional arguments} 51 | \centering \url{http://stackoverflow.com/q/11831070/184363} 52 | \end{block} 53 | \end{frame} 54 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/36.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{36. Pasando funciones a iter()} 5 | \begin{block}{} 6 | \Large 7 | \centering iter(function, sentinel) 8 | \end{block} 9 | 10 | \small 11 | \begin{alertblock}{} 12 | \centering 13 | El uso más habitual de \structure{iter()} es pasarle un único 14 | argumento --- el objeto sobre el que queremos iterar. Pero también 15 | podemos pasarle una \structure{función}, que es ejecutada una y 16 | otra vez: en el momento en el que uno de los valores que devuelve 17 | sea igual a \structure{sentinel}, nos detenemos. 18 | \end{alertblock} 19 | \end{frame} 20 | 21 | \begin{frame}[fragile]{36. Pasando funciones a iter()} 22 | \small 23 | \begin{exampleblock} 24 | {Lee un fichero hasta la primera línea vacía:} 25 | \begin{lstlisting} 26 | with open('currículum.tex') as fd: 27 | for linea in iter(fd.readline, '\n'): 28 | print linea 29 | \end{lstlisting} 30 | \end{exampleblock} 31 | \end{frame} 32 | 33 | \begin{frame}[fragile]{36. Pasando funciones a iter()} 34 | \small 35 | \begin{exampleblock} 36 | {Genera números aleatorios hasta llegar a cero:} 37 | \begin{lstlisting} 38 | import random 39 | 40 | def aleatorio(): 41 | return random.randint(-10, 10) 42 | 43 | for numero in iter(aleatorio, 0): 44 | print numero 45 | \end{lstlisting} 46 | \end{exampleblock} 47 | \end{frame} 48 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/37.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{37. Autocompletado en el intérprete} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | En nuestro fichero \structure{.pythonrc}, estas líneas bastan para 9 | habilitar el \structure{autocompletado}, que se activa al pulsar 10 | tabulador, como estamos acostumbrados a hacer en la línea de 11 | comandos. 12 | \end{block} 13 | 14 | \begin{exampleblock}{} 15 | \begin{lstlisting} 16 | import readline 17 | import rlcompleter 18 | readline.parse_and_bind("tab: complete") 19 | \end{lstlisting} 20 | \end{exampleblock} 21 | 22 | \footnotesize 23 | \begin{alertblock}{} 24 | \centering 25 | ¡La variable de entorno \structure{PYTHONSTARTUP} debe apuntar a este fichero! 26 | \end{alertblock} 27 | \end{frame} 28 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/38.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{38. Historia de comandos} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | También podemos habilitar la historia de \structure{todo lo que 9 | hemos escrito} en el intérprete de Python, accesibles pulsando 10 | las \structure{teclas de navegación} vertical. Al igual que en una 11 | terminal cualquiera, la historia se guarda en un fichero, por lo 12 | que podemos reusar los comandos \structure{de una sesión a otra}. 13 | \end{block} 14 | 15 | \footnotesize 16 | \begin{exampleblock}{} 17 | \begin{lstlisting} 18 | import atexit 19 | import os.path 20 | import readline 21 | 22 | history_file = os.path.expanduser('~/.python_history') 23 | if os.path.exists(history_file): 24 | readline.read_history_file(history_file) 25 | func = readline.write_history_file 26 | atexit.register(func, history_file) 27 | \end{lstlisting} 28 | \end{exampleblock} 29 | \end{frame} 30 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/39.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{39. Límite de memoria} 5 | \small 6 | \begin{block}{} 7 | \centering 8 | Antes hemos mencionado que crear una lista de tamaño excesivo 9 | podría usar \structure{toda la memoria} del ordenador, a veces con 10 | trágicas consecuencias. Usando esto podemos impedir que Python use 11 | más del 3/4 de la memoria total de nuestro equipo, abortando la 12 | ejecución \structure{si sobrepasamos este límite}. 13 | \end{block} 14 | 15 | \scriptsize 16 | \begin{exampleblock}{} 17 | \begin{lstlisting} 18 | def get_ram_size(): 19 | with open('/proc/meminfo', 'rt') as fd: 20 | regexp = "^MemTotal:\s*(\d+) kB$" 21 | match = re.match(regexp, fd.read(), re.MULTILINE) 22 | return int(match.group(1)) * 1024 # kB to bytes 23 | MAX_RAM = get_ram_size() * 0.75 24 | resource.setrlimit(resource.RLIMIT_AS, 25 | (MAX_RAM, resource.RLIM_INFINITY)) 26 | \end{lstlisting} 27 | \end{exampleblock} 28 | \end{frame} 29 | 30 | \begin{frame}[fragile]{39. Límite de memoria} 31 | \footnotesize 32 | \begin{exampleblock} 33 | {Esto es lo que ocurre entonces si abarcamos demasiado:} 34 | \begin{lstlisting} 35 | >>> list(xrange(10e12)) 36 | Traceback (most recent call last): 37 | File ``'', line 1, in 38 | MemoryError 39 | \end{lstlisting} 40 | \end{exampleblock} 41 | 42 | \small 43 | \begin{block} 44 | {\centering Por si alguien quiere reusar mi fichero .pythonrc} 45 | \centering \url{http://github.com/vterron/dotfiles} 46 | \end{block} 47 | \end{frame} 48 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/features/40.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2013 2 | % License: CC BY-SA 4.0 3 | 4 | \begin{frame}[fragile]{40. a, *b, c = range(5)} 5 | \begin{exampleblock} 6 | {\centering Un detalle precioso de Py3K} 7 | \small 8 | \begin{lstlisting}[escapechar=!] 9 | >>> primero, !\color{blue}{*resto}! = range(5) 10 | >>> primero 11 | 0 12 | >>> resto 13 | [1, 2, 3, 4] 14 | >>> primero, !\color{blue}{*resto}!, ultimo = range(10) 15 | >>> primero 16 | 0 17 | >>> resto 18 | [1, 2, 3, 4, 5, 6, 7, 8] 19 | >>> ultimo 20 | 9 21 | \end{lstlisting} 22 | \end{exampleblock} 23 | \end{frame} 24 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/intro.tex: -------------------------------------------------------------------------------- 1 | \begin{frame}{Unknown Unknowns} 2 | \small 3 | \begin{block}{} 4 | \centering 5 | ``There are things we know that we know. There are known 6 | unknowns. That is to say there are things that we now know we 7 | don't know. But there are also \structure{unknown unknowns}. There 8 | are things we do not know we don't know'' [Donald Rumsfeld, 2002] 9 | \end{block} 10 | 11 | \small 12 | \begin{itemize} 13 | \item En Python hay funcionalidades increíbles, 14 | \structure{imprescindibles una vez que las conoces}, que 15 | podríamos no echar en falta jamás porque ni siquiera sabíamos 16 | que existían. 17 | \item El propósito de esta charla es presentar una serie de 18 | aspectos interesantes de Python que en estos años he descubierto 19 | que mucha gente, incluso programadores veteranos, desconoce. 20 | \end{itemize} 21 | \end{frame} 22 | 23 | \begin{frame}{Unknown Unknowns} 24 | \begin{itemize} 25 | \item Algunas de las funcionalidades que vamos a discutir aquí son 26 | muy prácticas y otras curiosidades de indiscutiblemente escasa o 27 | nula utilidad en nuestro día a día. Pero todos ellos son 28 | conceptos \structure{sencillos de entender} y que merece la pena 29 | saber que están ahí, incluso si no los usamos... por ahora. 30 | \item Tenemos 1:15 minutos para cada uno de los puntos, así que 31 | muchos de ellos sólo vamos a poder \structure{verlos muy por 32 | encima}. Pero al menos habrán dejado de ser \emph{unknown 33 | unknowns}. 34 | \end{itemize} 35 | \end{frame} 36 | 37 | \begin{frame}{¡No os limitéis a escuchar!} 38 | \begin{center} 39 | No suele ser divertido escuchar a nadie hablar durante casi una 40 | hora. Participad, intervenid, criticad, opinad. ¡Si digo algo que 41 | no tiene ningún sentido, \structure{corregidme}! 42 | \end{center} 43 | 44 | \begin{block}{\centering El código fuente está disponible en:} 45 | \centering \url{http://github.com/vterron/PyConES-2013} 46 | \end{block} 47 | 48 | \begin{center} 49 | \small Erratas, correcciones, enlaces interesantes...\\ ¿enviará 50 | alguien algún pull request antes de que termine esta charla? 51 | \end{center} 52 | \end{frame} 53 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/CREDITS: -------------------------------------------------------------------------------- 1 | I use a few images, found on the Internet, in my slides. Although 2 | I'm not a copyright expert, I believe that my use of these images 3 | here constitutes fair use: 4 | 5 | "[...] the fair use of a copyrighted work, including such use by 6 | reproduction in copies or phonorecords or by any other means specified 7 | by that section, for purposes such as criticism, comment, news 8 | reporting, teaching (including multiple copies for classroom use), 9 | scholarship, or research, is not an infringement of copyright." 10 | 11 | https://en.wikipedia.org/wiki/Fair_use 12 | 13 | On the other hand, re-distribution of the materials may very well not 14 | be considered "fair use". I'm including the graphics and images I use 15 | in this repository so as to make it easy for anybody else to use them 16 | for "fair use" purposes only, and I'm explicitly noting them to not be 17 | under my copyright nor licensed as my materials are. 18 | 19 | If you are the owner of such material and would like to have me remove 20 | it, please just let me know. 21 | 22 | ------------------------------------------------------------------- 23 | The above paragraphs are heavily based on Jan Schaumann's 24 | "Non-copyright / licensed materials" section (CC BY 3.0) on GitHub: 25 | https://github.com/jschauma/cs631apue/blob/master/README.md 26 | ------------------------------------------------------------------- 27 | 28 | - Anuncio Limón y Nada ("Un Palo"): 29 | https://www.youtube.com/watch?v=iECvWfs5ncA 30 | 31 | - A Clockwork Orange (Stanley Kubrick, 1971) 32 | https://en.wikipedia.org/wiki/A_Clockwork_Orange_%28film%29 33 | 34 | - xkcd: Python: 35 | http://xkcd.com/353/ 36 | 37 | - Trollface / Coolface / Problem? 38 | http://knowyourmeme.com/memes/trollface-coolface-problem 39 | 40 | - OMG Rage Face: 41 | http://knowyourmeme.com/memes/oh-crap-omg-rage-facea 42 | 43 | - First Day on the Internet Kid: 44 | http://knowyourmeme.com/memes/first-day-on-the-internet-kid 45 | 46 | - Houston Shaolin Kung Fu School: 47 | http://texaslunarfest.com/schedule/kung-fu-cropped/ 48 | -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/a-clockwork-orange-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/a-clockwork-orange-2.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/a-clockwork-orange.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/a-clockwork-orange.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/first-day-internet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/first-day-internet.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/omg-face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/omg-face.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/shaolin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/shaolin.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/trollface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/trollface.png -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/un-palo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/un-palo.jpg -------------------------------------------------------------------------------- /[2013] Forty Features of Python that You May Not Know/pics/xkcd-353.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2013] Forty Features of Python that You May Not Know/pics/xkcd-353.png -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/Makefile: -------------------------------------------------------------------------------- 1 | # Inspired by Stephan Bourduas's LaTeX Makefile: 2 | # http://www.iml.ece.mcgill.ca/~stephan/node/13 3 | 4 | SHELL := /bin/bash 5 | 6 | # Run all Python scripts, save output 7 | OUTPUTS_SCRIPT=./generate-outputs.py 8 | CODE_ROOT=./code/ 9 | CODE_OUTPUT=output 10 | 11 | PDFLATEX=pdflatex 12 | PDFLATEX_OPTS=-interaction=nonstopmode -halt-on-error -shell-escape 13 | 14 | BASENAME=python-classes 15 | TEX_FILE=${BASENAME}.tex 16 | PDF_FILE=${BASENAME}.pdf 17 | 18 | .PHONY: all pdf clean cover 19 | 20 | all : pdf cover 21 | 22 | cover: pdf 23 | pdf2svg $(PDF_FILE) pics/cover.svg 24 | 25 | pdf: $(TEX_FILE) 26 | $(OUTPUTS_SCRIPT) $(CODE_ROOT) $(CODE_OUTPUT) 27 | $(PDFLATEX) $(PDFLATEX_OPTS) $(TEX_FILE) 28 | $(PDFLATEX) $(PDFLATEX_OPTS) $(TEX_FILE) 29 | 30 | clean: 31 | rm -fv *.{aux,log,nav,out,snm,toc,vrb} 32 | rm -rf $(CODE_ROOT)/*/$(CODE_OUTPUT) 33 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/README.md: -------------------------------------------------------------------------------- 1 | The slides of the talk I gave at [PyConES 2014](http://2014.es.pycon.org/) (Zaragoza, Spain). 2 | 3 | [![Front](./pics/cover.svg)][pdf] 4 | 5 | They are also [available as a PDF][pdf], always up-to-date via [a GitHub action](../.github/workflows/python-classes.yml). 6 | 7 | - Title: *Classes in Python: You're Doing it Wrong* 8 | - Language: Spanish 9 | - License: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 10 | 11 | [pdf]: https://static.vterron.xyz/python-classes.pdf 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/00/00-new-style-example.py: -------------------------------------------------------------------------------- 1 | class Perro(object): 2 | 3 | def __init__(self, nombre, raza, edad): 4 | self.nombre = nombre 5 | self.raza = raza 6 | self.edad = edad 7 | 8 | mascota = Perro("Lassie", "Collie", 18) 9 | print "Clase:", mascota.__class__ 10 | print "Tipo:", type(mascota) 11 | 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/00/01-old-style-example.py: -------------------------------------------------------------------------------- 1 | class Perro: # no heredamos de 'object' 2 | 3 | def __init__(self, nombre, raza, edad): 4 | self.nombre = nombre 5 | self.raza = raza 6 | self.edad = edad 7 | 8 | sargento = Perro("Stubby", "Bull Terrier", 9) 9 | print "Clase:", sargento.__class__ 10 | print "Tipo:", type(sargento) 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/00/02-new-style-raise.py: -------------------------------------------------------------------------------- 1 | class Spam(object): 2 | pass 3 | 4 | raise Spam() 5 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/00/03-old-style-raise.py: -------------------------------------------------------------------------------- 1 | class Foo: 2 | pass 3 | 4 | raise Foo() 5 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/10-super-example-error.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class ListaLogger(list): 4 | def append(self, x): 5 | print "Intentando añadir", x 6 | self.append(x) 7 | 8 | numeros = ListaLogger() 9 | numeros.append(7) 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/11-super-example-py2k-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class ListaLogger(list): 4 | def append(self, x): 5 | print "Añadiendo", x, "a la lista (¡ahora sí!)" 6 | super(ListaLogger, self).append(x) 7 | 8 | numeros = ListaLogger() 9 | numeros.append(7) 10 | print numeros 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/12-super-example-py2k-1.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | class Circulo(Punto): 7 | def __init__(self, x, y, radio): 8 | super(Circulo, self).__init__(x, y) 9 | self.radio = radio 10 | 11 | c = Circulo(3, 4, 5.5) 12 | print "x:", c.x 13 | print "y:", c.y 14 | print "r:", c.radio 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/13-super-example-py3k.py: -------------------------------------------------------------------------------- 1 | class ListaLogger(list): 2 | def append(self, x): 3 | print("Esto también añade", x) 4 | super().append(x) 5 | 6 | numeros = ListaLogger([4, 5]) 7 | numeros.append(-1) 8 | print(numeros) 9 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/14-multiple-inheritance-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Humano(object): 4 | def ataca(self): 5 | print "Puñetazo" 6 | 7 | class Cyborg(Humano): 8 | def ataca(self): 9 | print "Láser" 10 | 11 | class Ninja(Humano): 12 | def ataca(self): 13 | print "Shuriken" 14 | 15 | class T1000(Cyborg, Ninja): 16 | def ataca(self, n): 17 | for _ in xrange(n): 18 | super(T1000, self).ataca() 19 | 20 | print "MRO:", T1000.__mro__ 21 | robot = T1000() 22 | robot.ataca(5) 23 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/15-multiple-inheritance-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Humano(object): 4 | def ataca(self): 5 | print "Puñetazo" 6 | 7 | class Cyborg(Humano): 8 | pass 9 | 10 | class Ninja(Humano): 11 | def ataca(self): 12 | print "Shuriken" 13 | 14 | class T1000(Cyborg, Ninja): 15 | def ataca(self, n): 16 | for _ in xrange(n): 17 | super(T1000, self).ataca() 18 | 19 | robot = T1000() 20 | robot.ataca(5) 21 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/01/16-multiple-inheritance-2.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Humano(object): 4 | def ataca(self): 5 | print "Puñetazo" 6 | 7 | class Cyborg(Humano): 8 | def defiende(self): 9 | print "Armadura" 10 | 11 | class Ninja(Humano): 12 | def ataca(self): 13 | print "Shuriken" 14 | 15 | class T1000(Cyborg, Ninja): 16 | pass 17 | 18 | robot = T1000() 19 | robot.defiende() 20 | robot.ataca() 21 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/20-self-example.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Punto(object): 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distancia(self, otro): 9 | x_delta = self.x - otro.x 10 | y_delta = self.y - otro.y 11 | return math.sqrt(x_delta ** 2 + y_delta ** 2) 12 | 13 | c1 = Punto(8, 1) 14 | c2 = Punto(4, 7) 15 | print c1.distancia(c2) 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/21-this-example.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | def __init__(this, x, y): 3 | this.x = x 4 | this.y = y 5 | 6 | class Circulo(Punto): 7 | def __init__(this, x, y, radio): 8 | super(Circulo, this).__init__(x, y) 9 | this.radio = radio 10 | 11 | c = Circulo(2, 7, 5) 12 | print "x:", c.x 13 | print "y:", c.y 14 | print "r:", c.radio 15 | 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/22-if-self-were-optional.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Punto(object): 4 | def __init__(x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distancia(otro): 9 | x_delta = self.x - otro.x 10 | y_delta = self.y - otro.y 11 | return math.sqrt(x_delta ** 2 + y_delta ** 2) 12 | 13 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/23-self-error.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | p = Punto(1) 7 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/24-method-call-equivalency.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Punto(object): 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distancia(self, otro): 9 | x_delta = self.x - otro.x 10 | y_delta = self.y - otro.y 11 | return math.sqrt(x_delta ** 2 + y_delta ** 2) 12 | 13 | c1 = Punto(4, 1.5) 14 | c2 = Punto(3, 3.1) 15 | print c1.distancia(c2) == Punto.distancia(c1, c2) 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/02/25-self-add-method.py: -------------------------------------------------------------------------------- 1 | class C(object): 2 | pass 3 | 4 | def init_x(clase, valor): 5 | clase.x = valor 6 | 7 | C.init_x = init_x 8 | 9 | c = C() 10 | c.init_x(23) 11 | print c.x 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/30-class-variable-example-0.py: -------------------------------------------------------------------------------- 1 | class T1000(object): 2 | jefe = "Skynet" 3 | 4 | robot1 = T1000() 5 | robot2 = T1000() 6 | 7 | print robot1.jefe 8 | print robot2.jefe 9 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/31-class-variable-example-1.py: -------------------------------------------------------------------------------- 1 | class T1000(object): 2 | jefe = "Skynet" 3 | 4 | robot1 = T1000() 5 | robot2 = T1000() 6 | 7 | # Esto no cambia T1000.jefe 8 | robot2.jefe = "James Cameron" 9 | 10 | print robot1.jefe 11 | print robot2.jefe 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/32-defining-constants-0.py: -------------------------------------------------------------------------------- 1 | class Constantes(object): 2 | pi = 3.141592653589793 3 | 4 | print "Pi:", Constantes.pi 5 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/33-defining-constants-1.py: -------------------------------------------------------------------------------- 1 | PI = 3.141592653589793 2 | 3 | class Circulo(object): 4 | def __init__(self, x, y, radio): 5 | self.x = x 6 | self.y = y 7 | self.radio = radio 8 | 9 | def area(self): 10 | return PI * (self.radio ** 2) 11 | 12 | c = Circulo(0, 0, 4.5) 13 | print "Pi:", c.area() 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/34-initializing-to-None-0.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | 3 | x = 0 4 | y = 0 5 | 6 | def __init__(self, x, y): 7 | self.x = x 8 | self.y = y 9 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/35-initializing-to-None-1.py: -------------------------------------------------------------------------------- 1 | class Circulo(object): 2 | 3 | x = 0 4 | y = 0 5 | radio = 0 6 | 7 | def __init__(self, x, y, radio): 8 | self.x = x 9 | self.y = y 10 | self.raido = radio # typo! 11 | 12 | c = Circulo(1, 3, 4) 13 | print "Radio:", c.radio 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/03/36-self-or-class-name.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class T1000(object): 4 | 5 | JEFE = "Skynet" 6 | 7 | def saluda_uno(self): 8 | print self.JEFE, "me envía a eliminarte" 9 | 10 | def saluda_dos(self): 11 | print T1000.JEFE, "me envía a eliminarte" 12 | 13 | robot = T1000() 14 | robot.saluda_uno() 15 | robot.saluda_dos() 16 | 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/40-private-example.py: -------------------------------------------------------------------------------- 1 | class Persona(object): 2 | 3 | def __init__(self, nombre, secreto): 4 | self.nombre = nombre 5 | self._secreto = secreto 6 | 7 | p = Persona("Raquel", "Prefiere Perl") 8 | print "Nombre:", p.nombre 9 | print "Secreto:", p._secreto 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/41-private-bad-idea.py: -------------------------------------------------------------------------------- 1 | class Persona(object): 2 | 3 | def __init__(self, nombre, secreto): 4 | self.nombre = nombre 5 | self._secreto = secreto 6 | 7 | p = Persona("Raquel", "Prefiere Perl") 8 | print "Secreto:", p._secreto 9 | 10 | p._secreto = "Programa en Notepad" 11 | print "Secreto:", p._secreto 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/42-method-with-same-name.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Persona(object): 4 | 5 | # Máxima edad confesada en público 6 | MAXIMA_EDAD = 35 7 | 8 | def __init__(self, nombre, edad): 9 | self.nombre = nombre 10 | self._edad = edad 11 | 12 | def edad(self): 13 | return min(self._edad, self.MAXIMA_EDAD) 14 | 15 | p = Persona("Juan Pedro", 41) 16 | print "Nombre:", p.nombre 17 | print "Edad:", p.edad() 18 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/43-mangled-example-0.py: -------------------------------------------------------------------------------- 1 | class Persona(object): 2 | 3 | def __init__(self, nombre, edad): 4 | self.nombre = nombre 5 | self.__edad = edad 6 | 7 | p = Persona("Juan Pedro", 23) 8 | print "Nombre:", p.nombre 9 | print "Edad:", p.__edad 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/44-mangled-example-1.py: -------------------------------------------------------------------------------- 1 | class Persona(object): 2 | 3 | def __init__(self, nombre, edad): 4 | self.nombre = nombre 5 | self.__edad = edad 6 | 7 | p = Persona("Juan Pedro", 23) 8 | print "Edad:", p._Persona__edad 9 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/45-mangled-why-we-need-them-0.py: -------------------------------------------------------------------------------- 1 | class Habitacion(object): 2 | _PIN = 9348 3 | 4 | class CamaraAcorazada(Habitacion): 5 | def __init__(self, PIN): 6 | self._PIN = PIN 7 | 8 | p = CamaraAcorazada(2222) 9 | print "PIN:", p._PIN # sobreescribe PIN de Habitacion 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/46-mangled-why-we-need-them-1.py: -------------------------------------------------------------------------------- 1 | class Habitacion(object): 2 | __PIN = 9348 3 | 4 | class CamaraAcorazada(Habitacion): 5 | def __init__(self, PIN): 6 | self.__PIN = PIN 7 | 8 | p = CamaraAcorazada(2222) 9 | print "PIN1:", p._Habitacion__PIN 10 | print "PIN2:", p._CamaraAcorazada__PIN 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/04/47-mangled-why-we-need-them-2.py: -------------------------------------------------------------------------------- 1 | class Habitacion(object): 2 | __PIN = 9348 3 | 4 | class CamaraAcorazada(Habitacion): 5 | def __init__(self, PIN): 6 | self.__PIN = PIN 7 | 8 | def PIN1(self): 9 | return self._Habitacion__PIN 10 | 11 | def PIN2(self): 12 | return self.__PIN 13 | 14 | p = CamaraAcorazada(2222) 15 | print "PIN1:", p.PIN1() 16 | print "PIN2:"; p.PIN2() 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/50-staticmethod-example-0.py: -------------------------------------------------------------------------------- 1 | class Calculadora(object): 2 | 3 | def __init__(self, nombre): 4 | self.nombre = nombre 5 | 6 | def modelo(self): 7 | return self.nombre 8 | 9 | def suma(self, x, y): 10 | return x + y 11 | 12 | c = Calculadora("Multivac") 13 | print c.modelo() 14 | print c.suma(4, 8) 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/51-staticmethod-example-1.py: -------------------------------------------------------------------------------- 1 | class Calculadora(object): 2 | 3 | def __init__(self, nombre): 4 | self.nombre = nombre 5 | 6 | def modelo(self): 7 | return self.nombre 8 | 9 | @staticmethod 10 | def suma(x, y): 11 | return x + y 12 | 13 | c = Calculadora("Multivac") 14 | print c.modelo() 15 | print c.suma(4, 8) 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/52-staticmethod-example-2.py: -------------------------------------------------------------------------------- 1 | class Calculadora(object): 2 | 3 | def __init__(self, nombre): 4 | self.nombre = nombre 5 | 6 | def modelo(self): 7 | return self.nombre 8 | 9 | @staticmethod 10 | def suma(x, y): 11 | return x + y 12 | 13 | print Calculadora.suma(4, 8) 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/53-new-object-problem-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Ameba(object): 4 | 5 | def __init__(self, nombre): 6 | self.nombre = nombre 7 | 8 | def fision(self): 9 | h1 = Ameba("Primogénito") 10 | h2 = Ameba("Benjamín") 11 | return h1, h2 12 | 13 | ameba = Ameba("Foraminifera") 14 | hijo1, hijo2 = ameba.fision() 15 | print "Hijo 1:", hijo1.nombre 16 | print "Hijo 2:", hijo2.nombre 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/54-new-object-problem-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Ameba(object): 4 | 5 | def __init__(self, nombre): 6 | self.nombre = nombre 7 | 8 | def fision(self): 9 | h1 = Ameba("Primogénito") 10 | h2 = Ameba("Benjamín") 11 | return h1, h2 12 | 13 | class AmebaCyborg(Ameba): 14 | pass 15 | 16 | ameba = AmebaCyborg("Foraminifera T-800") 17 | hijo1, hijo2 = ameba.fision() 18 | print "Hijo 1 es", type(hijo1) 19 | print "Hijo 2 es", type(hijo2) 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/55-new-object-problem-2.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | class Ameba(object): 3 | 4 | def __init__(self, nombre): 5 | self.nombre = nombre 6 | 7 | def fision(self): 8 | cls1 = self.__class__ 9 | h1 = cls1("Primogénito") 10 | # O también... 11 | cls2 = type(self) 12 | h2 = cls2("Benjamín") 13 | return h1, h2 14 | 15 | ameba = Ameba("Foraminifera") 16 | hijo1, hijo2 = ameba.fision() 17 | print "Hijo 1:", hijo1.nombre 18 | print "Hijo 2:", hijo2.nombre 19 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/56-new-object-problem-3.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | class Ameba: 3 | 4 | def __init__(self, nombre): 5 | self.nombre = nombre 6 | 7 | def fision(self): 8 | clase = type(self) 9 | print "Mi tipo es:", clase 10 | h1 = clase("Primogénito") 11 | h2 = clase("Benjamín") 12 | return h1, h2 13 | 14 | ameba = Ameba("Foraminifera") 15 | ameba.fision() 16 | 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/57-classmethod-example-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Ameba(object): 4 | 5 | def __init__(self, nombre): 6 | self.nombre = nombre 7 | 8 | @classmethod 9 | def fision(cls): 10 | h1 = cls("Primogénito") 11 | h2 = cls("Benjamín") 12 | return h1, h2 13 | 14 | ameba = Ameba("Foraminifera") 15 | hijo1, hijo2 = ameba.fision() 16 | print "Hijo 1:", hijo1.nombre 17 | print "Hijo 2:", hijo2.nombre 18 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/05/58-classmethod-example-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Ameba(object): 4 | 5 | def __init__(self, nombre): 6 | self.nombre = nombre 7 | 8 | def fision(self): 9 | cls = type(self) 10 | ascendencia = ", hijo de " + self.nombre 11 | h1 = cls("Primogénito" + ascendencia) 12 | h2 = cls("Benjamín" + ascendencia) 13 | return h1, h2 14 | 15 | ameba = Ameba("Foraminifera") 16 | hijo1, hijo2 = ameba.fision() 17 | print "Hijo 1:", hijo1.nombre 18 | print "Hijo 2:", hijo2.nombre 19 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/600-getter-example-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import math 4 | 5 | class Circulo(object): 6 | 7 | def __init__(self, radio): 8 | self.radio = radio 9 | self.area = math.pi * radio ** 2 10 | 11 | c = Circulo(1) 12 | print "Radio:", c.radio 13 | print "Área:", c.area 14 | print 15 | 16 | c.radio = 2 17 | print "Radio:", c.radio 18 | print "Área:", c.area 19 | 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/601-getter-example-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | import math 3 | 4 | class Circulo(object): 5 | 6 | def __init__(self, radio): 7 | self.radio = radio 8 | 9 | def area(self): 10 | return math.pi * self.radio ** 2 11 | 12 | c = Circulo(1) 13 | print "Radio:", c.radio 14 | print "Área:", c.area() 15 | c.radio = 2 16 | print "Radio:", c.radio 17 | print "Área:", c.area() 18 | 19 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/602-setter-example-0.py: -------------------------------------------------------------------------------- 1 | class Circulo(object): 2 | 3 | def __init__(self, radio): 4 | self.radio = radio 5 | 6 | c = Circulo(13) 7 | print "Radio:", c.radio 8 | c.radio = -2 9 | print "Radio:", c.radio 10 | 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/603-setter-example-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | class Circulo(object): 3 | 4 | def __init__(self, radio): 5 | self._radio = radio 6 | 7 | def set_radio(self, radio): 8 | if radio < 0: 9 | raise ValueError("'radio' debe ser un número no negativo") 10 | self._radio = radio 11 | 12 | c = Circulo(3.5) 13 | print "Radio:", c._radio 14 | c.set_radio(-2) 15 | print "Radio:", c._radio 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/604-setters-getters-example.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class CajaFuerte(object): 4 | 5 | def __init__(self, PIN): 6 | self._PIN = PIN 7 | 8 | def get_PIN(self): 9 | print "Enviando copia a la NSA..." 10 | return self._PIN 11 | 12 | hucha = CajaFuerte(7821) 13 | print "PIN:", hucha.get_PIN() 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/605-properties-example.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class CajaFuerte(object): 4 | 5 | def __init__(self, PIN): 6 | self.PIN = PIN 7 | 8 | @property 9 | def PIN(self): 10 | print "Enviando copia a la NSA..." 11 | return self._PIN 12 | 13 | @PIN.setter 14 | def PIN(self, PIN): 15 | if len(str(PIN)) != 4: 16 | raise ValueError("'PIN' ha de tener cuatro dígitos") 17 | self._PIN = PIN 18 | 19 | hucha = CajaFuerte(7814) 20 | print "PIN:", hucha.PIN 21 | hucha.PIN = 880 22 | 23 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/606-property-fget.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import math 4 | 5 | class Circulo(object): 6 | 7 | def __init__(self, radio): 8 | self.radio = radio 9 | 10 | @property 11 | def area(self): 12 | return math.pi * self.radio ** 2 13 | 14 | c = Circulo(1) 15 | print "Radio:", c.radio 16 | print "Área:", c.area 17 | print 18 | 19 | c.radio = 2 20 | print "Radio:", c.radio 21 | print "Área:", c.area 22 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/607-property-fset.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Circulo(object): 4 | 5 | def __init__(self, radio): 6 | self.radio = radio 7 | 8 | @property 9 | def radio(self): 10 | return self._radio 11 | 12 | @radio.setter 13 | def radio(self, radio): 14 | if radio < 0: 15 | raise ValueError("'radio' debe ser un número no negativo") 16 | self._radio = radio 17 | 18 | c = Circulo(13) 19 | print "Radio:", c.radio 20 | c.radio = -2 21 | print "Radio:", c.radio 22 | 23 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/608-property-deleter-usage.py: -------------------------------------------------------------------------------- 1 | # No podemos usar 'import' por los guiones 2 | modulo = __import__("608-property-deleter") 3 | 4 | hucha = modulo.CajaFuerte(7814) 5 | print "PIN:", hucha.PIN 6 | hucha.PIN = 8808 7 | print "PIN:", hucha.PIN 8 | print "Historial:", hucha._PINs 9 | del hucha.PIN 10 | print "PIN:", hucha.PIN 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/608-property-deleter.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | class CajaFuerte(object): 3 | def __init__(self, PIN): 4 | self._PINs = [] 5 | self.PIN = PIN 6 | 7 | @property 8 | def PIN(self): 9 | try: 10 | return self._PINs[-1] 11 | except IndexError: 12 | return None 13 | 14 | @PIN.setter 15 | def PIN(self, PIN): 16 | if len(str(PIN)) != 4: 17 | raise ValueError("'PIN' ha de tener cuatro dígitos") 18 | self._PINs.append(PIN) 19 | 20 | @PIN.deleter 21 | def PIN(self): 22 | del self._PINs[:] 23 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/609-fget-docstring.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import math 4 | 5 | class Circulo(object): 6 | 7 | def __init__(self, radio): 8 | self.radio = radio 9 | 10 | @property 11 | def area(self): 12 | """Devuelve al área del círculo. """ 13 | return math.pi * self.radio ** 2 14 | 15 | c = Circulo(3.4) 16 | print "Radio:", c.radio 17 | print "Área:", c.area 18 | print "Docstring:", Circulo.area.__doc__ 19 | 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/610-name-unmatch.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | class Circulo(object): 3 | 4 | def __init__(self, radio): 5 | self.radio = radio 6 | 7 | @property 8 | def radio(self): 9 | return self._radio 10 | 11 | @radio.setter 12 | def set_radio(self, radio): 13 | if radio < 0: 14 | raise ValueError("'radio' debe ser un número no negativo") 15 | self._radio = radio 16 | 17 | c = Circulo(13) 18 | print "Radio:", c.radio 19 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/611-property-function.py: -------------------------------------------------------------------------------- 1 | class CajaFuerte(object): 2 | def __init__(self, PIN): 3 | self.PIN = PIN 4 | 5 | def get_PIN(self): 6 | return self._PIN 7 | 8 | def set_PIN(self, PIN): 9 | print "Enviando copia a la NSA..." 10 | self._PIN = PIN 11 | 12 | def delete_PIN(self): 13 | self.PIN = None 14 | 15 | PIN = property(get_PIN, set_PIN, delete_PIN, "La clave de acceso") 16 | 17 | hucha = CajaFuerte(7814) 18 | print "PIN:", hucha.PIN 19 | print "Docstring:", CajaFuerte.PIN.__doc__ 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/612-setter-and-deleter.py: -------------------------------------------------------------------------------- 1 | class CajaFuerte(object): 2 | 3 | def __init__(self, PIN): 4 | self.PIN = PIN 5 | 6 | def set_PIN(self, PIN): 7 | print "Enviando copia a la NSA..." 8 | self._PIN = PIN 9 | 10 | def delete_PIN(self): 11 | self.PIN = None 12 | 13 | PIN = property(fset=set_PIN, fdel=delete_PIN) 14 | 15 | hucha = CajaFuerte(7814) 16 | del hucha.PIN 17 | print "PIN:", hucha.PIN 18 | 19 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/06/613-deleter-error.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import math 4 | 5 | class Circulo(object): 6 | 7 | def __init__(self, radio): 8 | self.radio = radio 9 | 10 | @property 11 | def area(self): 12 | return math.pi * self.radio ** 2 13 | 14 | c = Circulo(1.5) 15 | print "Área:", c.area 16 | del c.area 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/700-neither-str-nor-repr.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Triangulo(object): 4 | 5 | def __init__(self, base, altura): 6 | self.base = base 7 | self.altura = altura 8 | 9 | @property 10 | def area(self): 11 | return (self.base * self.altura) / 2.0 12 | 13 | t = Triangulo(2, 3) 14 | print "Triángulo:", t 15 | print "Área:", t.area 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/701-str-example-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Triangulo(object): 4 | 5 | def __init__(self, base, altura): 6 | self.base = base 7 | self.altura = altura 8 | 9 | @property 10 | def area(self): 11 | return (self.base * self.altura) / 2.0 12 | 13 | def __str__(self): 14 | msg = "Triángulo de base {0} y altura {1}" 15 | return msg.format(self.base, self.altura) 16 | 17 | t = Triangulo(2, 3) 18 | print str(t) 19 | print "Área:", t.area 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/702-str-example-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Triangulo(object): 4 | def __init__(self, base, altura): 5 | self.base = base 6 | self.altura = altura 7 | 8 | @property 9 | def area(self): 10 | return (self.base * self.altura) / 2.0 11 | 12 | def __str__(self): 13 | clase = type(self).__name__ 14 | msg = "{0} de base {1} y altura {2}" 15 | return msg.format(clase, self.base, self.altura) 16 | 17 | t = Triangulo(2, 3) 18 | print t 19 | print "Área:", t.area 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/703-repr-undefined.py: -------------------------------------------------------------------------------- 1 | class Triangulo(object): 2 | 3 | def __init__(self, base, altura): 4 | self.base = base 5 | self.altura = altura 6 | 7 | def __str__(self): 8 | clase = type(self).__name__ 9 | msg = "{0} de base {1} y altura {2}" 10 | return msg.format(clase, self.base, self.altura) 11 | 12 | t = Triangulo(2, 3) 13 | print repr(t) 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/704-repr-example.py: -------------------------------------------------------------------------------- 1 | class Triangulo(object): 2 | 3 | def __init__(self, base, altura): 4 | self.base = base 5 | self.altura = altura 6 | 7 | def __str__(self): 8 | clase = type(self).__name__ 9 | msg = "{0} de base {1} y altura {2}" 10 | return msg.format(clase, self.base, self.altura) 11 | 12 | def __repr__(self): 13 | clase = type(self).__name__ 14 | msg = "{0}({1}, {2})" 15 | return msg.format(clase, self.base, self.altura) 16 | 17 | t = Triangulo(2, 3) 18 | print repr(t) 19 | print eval(repr(t)) 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/705-repr-no-str.py: -------------------------------------------------------------------------------- 1 | class Triangulo(object): 2 | 3 | def __init__(self, base, altura): 4 | self.base = base 5 | self.altura = altura 6 | 7 | def __repr__(self): 8 | clase = type(self).__name__ 9 | msg = "{0}({1}, {2})" 10 | return msg.format(clase, self.base, self.altura) 11 | 12 | t = Triangulo(2, 3) 13 | print str(t) 14 | print repr(t) 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/07/706-datetime-str-and-repr.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | ahora = datetime.datetime.now() 4 | print "str() :", str(ahora) 5 | print "repr():", repr(ahora) 6 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/800-why-we-need-namedtuples-0.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | """ Punto (x, y, z) en un espacio tridimensional. """ 3 | 4 | def __init__(self, x, y, z): 5 | self.x = x 6 | self.y = y 7 | self.z = z 8 | 9 | p = Punto(3, 1, 5) 10 | print "x:", p.x 11 | print "y:", p.y 12 | print "z:", p.z 13 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/801-why-we-need-namedtuples-1.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | """ Punto (x, y, z) en un espacio tridimensional. """ 3 | 4 | def __init__(self, x, y, z): 5 | self.x = x 6 | self.y = y 7 | self.z = z 8 | 9 | p = Punto(3, 1, 5) 10 | print p 11 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/802-why-we-need-namedtuples-2.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | """ Punto (x, y, z) en un espacio tridimensional. """ 3 | 4 | def __init__(self, x, y, z): 5 | self.x = x 6 | self.y = y 7 | self.z = z 8 | 9 | def __repr__(self): 10 | args = (type(self).__name__, self.x, self.y, self.z) 11 | return "{0}({1}, {2}, {3})".format(*args) 12 | 13 | p1 = Punto(3, 1, 5) 14 | p2 = Punto(3, 1, 5) 15 | 16 | print p1, "==", p2, "?" 17 | print p1 == p2 18 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/803-why-we-need-namedtuples-3.py: -------------------------------------------------------------------------------- 1 | class Punto(object): 2 | """ Punto (x, y, z) en un espacio tridimensional. """ 3 | 4 | def __init__(self, x, y, z): 5 | self.x = x 6 | self.y = y 7 | self.z = z 8 | 9 | def __repr__(self): 10 | args = (type(self).__name__, self.x, self.y, self.z) 11 | return "{0}({1}, {2}, {3})".format(*args) 12 | 13 | def __eq__(self, other): 14 | return self.x == other.x and \ 15 | self.y == other.y and \ 16 | self.z == other.z 17 | 18 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/804-Point-with-namedtuple.py: -------------------------------------------------------------------------------- 1 | import collections 2 | Punto = collections.namedtuple("Punto", "x y z") 3 | 4 | p = Punto(3, 1, 5) 5 | print "x:", p.x 6 | print "y:", p.y 7 | print "z:", p.z 8 | 9 | p2 = Punto(3, 1, 5) 10 | print p2 11 | print p == p2 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/805-namedtuple-explained.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import collections 4 | 5 | Punto = collections.namedtuple("Punto", "x y z") 6 | 7 | p = Punto(4, 3, 7) 8 | print "x:", p.x 9 | print "y:", p[1] 10 | print "z:", p[-1] 11 | print "Tamaño:", len(p) 12 | 13 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/806-namedtuple-field_names.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | import collections 4 | 5 | # Todas estas llamadas son equivalentes 6 | collections.namedtuple("Punto", ["x", "y", "z"]) 7 | collections.namedtuple("Punto", "x y z") 8 | collections.namedtuple("Punto", "x,y,z") 9 | collections.namedtuple("Punto", "x, y, z") 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/807-namedtuple-invalid-identifier.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | from collections import namedtuple 4 | Hucha = namedtuple("Hucha", "altura anchura _PIN") 5 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/808-namedtuple-rename.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | from collections import namedtuple 4 | Hucha = namedtuple("Hucha", "_PIN color for 1", rename=True) 5 | print Hucha._fields 6 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/809-namedtuple-why-typename.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | cls = collections.namedtuple("Punto", "x y z") 4 | print cls 5 | print "Nombre:", cls.__name__ 6 | 7 | p = cls(4, 3, 8) 8 | print p 9 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/810-Point-own-methods-0.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | import math 4 | 5 | Punto = collections.namedtuple("Punto", "x y z") 6 | class Punto(Punto): 7 | 8 | def distancia(self, other): 9 | """ Distancia entre dos puntos. """ 10 | x_axis = (self.x - other.x) ** 2 11 | y_axis = (self.y - other.y) ** 2 12 | z_axis = (self.z - other.z) ** 2 13 | return math.sqrt(x_axis + y_axis + z_axis) 14 | 15 | p1 = Punto(3, 1, 5) 16 | p2 = Punto(5, 2, 7) 17 | print "Distancia:", p1.distancia(p2) 18 | print 19 | print "MRO:", Punto.__mro__ 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/811-Point-own-methods-1.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import math 3 | 4 | _Punto = collections.namedtuple("_Punto", "x y z") 5 | class Punto(_Punto): 6 | 7 | def distancia(self, other): 8 | """ Distancia entre dos puntos. """ 9 | x_axis = (self.x - other.x) ** 2 10 | y_axis = (self.y - other.y) ** 2 11 | z_axis = (self.z - other.z) ** 2 12 | return math.sqrt(x_axis + y_axis + z_axis) 13 | 14 | print "MRO:", Punto.__mro__ 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/812-Point-own-methods-2.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import math 3 | 4 | class Punto(collections.namedtuple("_Punto", "x y z")): 5 | 6 | def distancia(self, other): 7 | """ Distancia entre dos puntos. """ 8 | x_axis = (self.x - other.x) ** 2 9 | y_axis = (self.y - other.y) ** 2 10 | z_axis = (self.z - other.z) ** 2 11 | return math.sqrt(x_axis + y_axis + z_axis) 12 | 13 | print "MRO:", Punto.__mro__ 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/813-Point-own-methods-3.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import math 3 | 4 | class Punto(collections.namedtuple("_Punto", "x y z")): 5 | 6 | def distancia(self, other): 7 | """ Distancia entre dos puntos. """ 8 | x_axis = (self.x - other.x) ** 2 9 | y_axis = (self.y - other.y) ** 2 10 | z_axis = (self.z - other.z) ** 2 11 | return math.sqrt(x_axis + y_axis + z_axis) 12 | 13 | def to_zero(self): 14 | """ Distancia al origen de coordenadas. """ 15 | cls = type(self) 16 | origen = cls(0, 0, 0) 17 | return self.distancia(origen) 18 | 19 | p = Punto(3, 4, 2) 20 | print "Distancia:", p.to_zero() 21 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/814-namedtuple-verbose.py: -------------------------------------------------------------------------------- 1 | import collections 2 | Punto = collections.namedtuple("Punto", "x y z", verbose=True) 3 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/815-namedtuple-asdict.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | Punto = collections.namedtuple("Punto", "x y z") 4 | p = Punto(8, 1, 3) 5 | print p._asdict() 6 | 7 | for atributo, valor in p._asdict().items(): 8 | print atributo, "->", valor 9 | 10 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/08/816-namedtuple-replace.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | Punto = collections.namedtuple("Punto", "x y z") 4 | p1 = Punto(8, 1, 3) 5 | print "Punto 1:", p1 6 | 7 | p2 = p1._replace(x = 7) 8 | print "Punto 2:", p2 9 | 10 | p3 = p1._replace(y = p2.z, z = -1) 11 | print "Punto 3:", p3 12 | 13 | print 14 | p3.x = 3 # AttributeError 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/900-why-we-need-new-0.py: -------------------------------------------------------------------------------- 1 | class Pesos(tuple): 2 | pass 3 | 4 | p = Pesos([0.75, 0.25]) 5 | print "Pesos:", p 6 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/901-why-we-need-new-1.py: -------------------------------------------------------------------------------- 1 | class Pesos(tuple): 2 | pass 3 | 4 | p = Pesos([0.50, 0.75, 0.25]) 5 | print "Pesos:", p 6 | print "Total:", sum(p) 7 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/902-why-we-need-new-2.py: -------------------------------------------------------------------------------- 1 | class Pesos(tuple): 2 | 3 | @property 4 | def total(self): 5 | return sum(self) 6 | 7 | def __init__(self, valores): 8 | if sum(self) != 1: 9 | msg = "la suma de los pesos ha de ser uno" 10 | raise ValueError(msg) 11 | 12 | p1 = Pesos([0.25, 0.75]) 13 | print "Pesos 1:", p1 14 | 15 | print 16 | p2 = Pesos([0.50, 0.75, 0.25]) # ValueError 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/903-why-we-need-new-3.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Pesos(tuple): 4 | 5 | @property 6 | def total(self): 7 | return sum(self) 8 | 9 | def __init__(self, valores): 10 | valores = [v / self.total for v in valores] 11 | super(Pesos, self).__init__(valores) 12 | 13 | p = Pesos([2, 1]) # [0.66, 0.33]... ¿no? 14 | print p 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/904-return-from-init-0.py: -------------------------------------------------------------------------------- 1 | class Pesos(tuple): 2 | 3 | @property 4 | def total(self): 5 | return sum(self) 6 | 7 | def __init__(self, valores): 8 | valores = [v / self.total for v in valores] 9 | self = super(Pesos, self).__init__(valores) 10 | return self 11 | 12 | p = Pesos([2, 1]) # sigue sin funcionar 13 | print p 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/905-return-from-init-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class Pesos(tuple): 4 | 5 | @property 6 | def total(self): 7 | return sum(self) 8 | 9 | def __init__(self, valores): 10 | valores = [v / self.total for v in valores] 11 | return tuple(valores) 12 | 13 | p = Pesos([2, 1]) # ¡tampoco! 14 | print p 15 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/906-immutable-init.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | variable = "Python" 4 | print "Antes :", variable 5 | variable.__init__("Java") # ¡nooo! 6 | print "Después:", variable 7 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/907-Pesos-with-new-0.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | class Pesos(tuple): 4 | 5 | def __new__(cls, valores): 6 | total = sum(valores) 7 | valores = [v / total for v in valores] 8 | return super(Pesos, cls).__new__(cls, valores) 9 | 10 | def __init__(self, valores): 11 | pass 12 | 13 | print Pesos([2, 1, 3]) 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/908-Pesos-with-new-1.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | class Pesos(tuple): 4 | 5 | def __new__(cls, valores): 6 | total = sum(valores) 7 | valores = [v / total for v in valores] 8 | return super(Pesos, cls).__new__(valores) 9 | 10 | def __init__(self, valores): 11 | pass 12 | 13 | print Pesos([2, 1, 3]) 14 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/909-Pesos-with-new-2.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | class Pesos(tuple): 4 | 5 | def __new__(cls, valores): 6 | total = sum(valores) 7 | valores = (v / total for v in valores) 8 | return super(Pesos, cls).__new__(cls, valores) 9 | 10 | @property 11 | def total(self): 12 | return sum(self) 13 | 14 | p = Pesos([2, 1, 3]) 15 | print "Pesos:", p 16 | print "Total:", p.total 17 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/910-AnswerToEverything-0.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class AnswerToEverything(object): 4 | 5 | def __new__(cls, x): 6 | print "¡En __new__()!" 7 | obj = super(AnswerToEverything, cls).__new__(cls) 8 | return obj 9 | 10 | def __init__(self, valor): 11 | print "¡En __init__()!" 12 | self.valor = 42 # ignora 'valor' 13 | 14 | def __str__(self): 15 | return str(self.valor) 16 | 17 | respuesta = AnswerToEverything(23) 18 | print "Respuesta:", respuesta 19 | 20 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/code/09/911-AnswerToEverything-1.py: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | class AnswerToEverything(object): 4 | 5 | def __new__(cls, x): 6 | print "¡En __new__()!" 7 | return 42 8 | 9 | def __init__(self, valor): 10 | # nada que hacer aquí 11 | print "¡En __init__()!" 12 | 13 | respuesta = AnswerToEverything(23) 14 | print "Respuesta:", respuesta 15 | 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/cover.tex: -------------------------------------------------------------------------------- 1 | { 2 | \usebackgroundtemplate{\includegraphics[height=1.0\paperheight]{pics/dog-no-idea.jpg}} 3 | 4 | \begin{frame}[plain] 5 | \vspace{7cm} 6 | \begin{TitleBox} 7 | {\large \inserttitle} \\ 8 | {\small \insertauthor \enspace --- \thinspace \url{https://vterron.xyz/classes}} 9 | \end{TitleBox} 10 | \end{frame} 11 | } 12 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/epilogue.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2014 2 | % Email: `echo vt2rron1iaa32s | tr 132 @.e` 3 | % License: CC BY-SA 4.0 4 | 5 | \begin{frame}{Programación orientada a objetos} 6 | \small 7 | \begin{block} 8 | {\centering Edsger W. Dijkstra} 9 | \centering 10 | ``[...] if 10 years from now, when you are doing something quick 11 | and dirty, you suddenly visualize that I am looking over your 12 | shoulders and say to yourself 'Dijkstra would not have liked 13 | this', well, that would be enough immortality for me''. 14 | [1995, \href{http://www.cs.utexas.edu/users/EWD/ewd12xx/EWD1213.PDF}{\structure{Fuente}}] 15 | \end{block} 16 | 17 | \begin{figure} 18 | \centering 19 | \includegraphics[height=3.5cm]{pics/dijkstra-2.jpg} 20 | \end{figure} 21 | \end{frame} 22 | 23 | \begin{frame}{\inserttitle} 24 | \begin{figure} 25 | \centering 26 | \includegraphics[height=4.25cm]{pics/dog-no-idea-2.jpg} 27 | \end{figure} 28 | 29 | \begin{block}{\centering Transparencias y código fuente en:} 30 | \centering \url{https://vterron.xyz/classes} 31 | \end{block} 32 | \end{frame} 33 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/generate-outputs.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python2 2 | 3 | # Author: Victor Terron (c) 2014 4 | # Email: `echo vt2rron1iaa32s | tr 132 @.e` 5 | # License: GNU GPLv3 6 | 7 | """ Walk the ROOT directory bottom-up and execute all Python scripts (*.py) 8 | we come across. The output of each script (both standard output and error) 9 | is written to a text file of the same name but without extension, stored in 10 | the OUTPUT directory (relative to the directory where the script is located). 11 | Lines are wrapped so that every line is at most 70 characters long. Only the 12 | first fifty output lines are written to each file. 13 | 14 | """ 15 | 16 | import os.path 17 | import subprocess 18 | import sys 19 | import textwrap 20 | 21 | ROOT = sys.argv[1] 22 | OUTPUT = sys.argv[2] 23 | 24 | for root, dirs, files in os.walk(ROOT, topdown=False): 25 | for file_ in sorted(files): 26 | basename, ext = os.path.splitext(file_) 27 | if ext == '.py': 28 | 29 | # Create output directory, if needed 30 | output_dir = os.path.join(root, OUTPUT) 31 | if not os.path.exists(output_dir): 32 | os.mkdir(output_dir) 33 | 34 | path = os.path.join(root, file_) 35 | print "Script:", path 36 | 37 | args = ['python', path] 38 | if basename.endswith('py3k'): 39 | args[0] = 'python3' 40 | 41 | output = os.path.join(output_dir, basename) 42 | kwargs = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 43 | process = subprocess.Popen(args, **kwargs) 44 | out = process.communicate()[0] 45 | 46 | with open(output, 'wt') as fd: 47 | for line in out.splitlines()[:50]: 48 | for wrapped_line in textwrap.wrap(line): 49 | fd.write(wrapped_line + '\n') 50 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/intro.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # encoding: UTF-8 3 | 4 | class Perro(object): 5 | 6 | def __init__(self, nombre, raza, edad): 7 | self.nombre = nombre 8 | self.raza = raza 9 | self.edad = edad 10 | 11 | def ladra(self): 12 | print self.nombre, "dice '¡Wooof!'" 13 | 14 | mascota = Perro("Lassie", "Collie", 18) 15 | mascota.ladra() 16 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/intro.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2014 2 | % Email: `echo vt2rron1iaa32s | tr 132 @.e` 3 | % License: CC BY-SA 4.0 4 | 5 | \begin{frame}{Programación orientada a objetos} 6 | \small 7 | \begin{block} 8 | {\centering Una cita apócrifa} 9 | \centering 10 | ``Object-oriented programming is an exceptionally bad 11 | idea which could only have originated in California'' 12 | [Edsger W. Dijkstra] 13 | \end{block} 14 | 15 | \begin{figure} 16 | \centering 17 | \includegraphics[height=4cm]{pics/dijkstra.jpg} 18 | \end{figure} 19 | \end{frame} 20 | 21 | \begin{frame}{Programación orientada a objetos} 22 | \small 23 | \begin{block} 24 | {\centering Lo que en realidad dijo} 25 | \centering 26 | ``For those who have wondered: I don't think object-oriented 27 | programming is a structuring paradigm that meets my standards of 28 | elegance.'' [Edsger W. Dijkstra, 1999] 29 | [\href{http://www.cs.utexas.edu/users/EWD/transcriptions/EWD12xx/EWD1284.html} 30 | {\structure{Fuente}}] 31 | \end{block} 32 | 33 | \begin{figure} 34 | \centering 35 | \includegraphics[height=5cm]{pics/like-a-sir.png} 36 | \end{figure} 37 | \end{frame} 38 | 39 | \begin{frame}{Programando clases en Python} 40 | \begin{block}{} 41 | \Large 42 | \centering 43 | El objetivo de esta charla es ayudarnos a hacer 44 | \structure{idiomáticas} y \structure{elegantes} nuestras clases en 45 | Python. 46 | \end{block} 47 | 48 | \begin{justify} 49 | En mayor o menor medida todo el mundo usa programación orientada a 50 | objetos, pero hay una serie de aspectos fundamentales que es 51 | indispensable conocer para evitar que nuestro código sea 52 | innecesariamente feo o complejo. 53 | \end{justify} 54 | \end{frame} 55 | 56 | \begin{frame}{Nuestra reacción a veces} 57 | \begin{figure} 58 | \centering 59 | \includegraphics[height=6cm]{pics/dont-want-to-live-on-this-planet.png} 60 | \end{figure} 61 | \end{frame} 62 | 63 | \begin{frame}{Programando clases en Python} 64 | \begin{alertblock}{} 65 | \small 66 | \centering 67 | La premisa es que somos mínimamente familiares con los 68 | \structure{conceptos básicos} de programación orientada a objetos, 69 | y que hemos trabajado un poco con nuestras propias clases en 70 | Python. 71 | \end{alertblock} 72 | 73 | \begin{figure} 74 | \centering 75 | \includegraphics[height=4cm]{pics/captain-obvious.jpg} 76 | \end{figure} 77 | \end{frame} 78 | 79 | \begin{frame}{Un muy brevísimo repaso} 80 | \small 81 | \begin{block}{\centering Uno} 82 | \centering 83 | Llamamos \structure{clase} a la representación abstracta de un 84 | concepto. Por ejemplo, 'perro', 'número entero' o 'servidor web'. 85 | \end{block} 86 | 87 | \begin{block}{\centering Dos} 88 | \centering 89 | Las clases se componen de \structure{atributos} y 90 | \structure{métodos}. 91 | \end{block} 92 | 93 | \begin{block}{\centering Tres} 94 | \centering 95 | Un objeto es cada una de las instancias de una clase. 96 | \end{block} 97 | \end{frame} 98 | 99 | \begin{frame}{Ejemplo: clase Perro} 100 | \pythoncode[fontsize=\footnotesize]{intro.py} 101 | \end{frame} 102 | 103 | \begin{frame}{¡No os limitéis a escuchar!} 104 | \begin{center} 105 | No suele ser divertido escuchar a nadie hablar durante casi una 106 | hora. Participad, intervenid, criticad, opinad. ¡Si digo algo que 107 | no tiene ningún sentido, \structure{corregidme}! 108 | \end{center} 109 | 110 | \begin{block}{\centering Transparencias y código fuente en:} 111 | \centering \url{https://vterron.xyz/classes} 112 | \end{block} 113 | 114 | \begin{center} 115 | \small Erratas, correcciones, enlaces, ¡cualquier cosa! 116 | \end{center} 117 | \end{frame} 118 | -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/captain-obvious.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/captain-obvious.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/dijkstra-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/dijkstra-2.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/dijkstra.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/dijkstra.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/dog-no-idea-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/dog-no-idea-2.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/dog-no-idea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/dog-no-idea.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/dont-want-to-live-on-this-planet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/dont-want-to-live-on-this-planet.png -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/game-developer-expectation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/game-developer-expectation.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/game-developer-reality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/game-developer-reality.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/like-a-sir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/like-a-sir.png -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/pair-programming-expectation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/pair-programming-expectation.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/pair-programming-reality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/pair-programming-reality.jpg -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/pics/programmer-two-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2014] Classes in Python: You're Doing it Wrong/pics/programmer-two-states.png -------------------------------------------------------------------------------- /[2014] Classes in Python: You're Doing it Wrong/puntos/00.tex: -------------------------------------------------------------------------------- 1 | % Author: Victor Terron (c) 2014 2 | % Email: `echo vt2rron1iaa32s | tr 132 @.e` 3 | % License: CC BY-SA 4.0 4 | 5 | \begin{frame}{00. Heredando de object (new-style)} 6 | \centering 7 | \small 8 | Hemos de heredar de \structure{object} para que nuestra clase sea 9 | \textit{new-style}. 10 | 11 | \footnotesize 12 | \pythoncode{./code/00/00-new-style-example.py} 13 | \pythonoutput{./code/00/output/00-new-style-example} 14 | 15 | \end{frame} 16 | 17 | \begin{frame}{00. Heredando de object: por qué} 18 | \begin{block}{Algo de historia} 19 | \centering Las clases \textit{new-style} aparecieron en Python 2.2 20 | (diciembre de 2001) 21 | \end{block} 22 | 23 | \begin{justify} 24 | Hasta Python 2.1, el concepto de clase no tenía relación con el 25 | tipo: los objetos de todas las (\textit{old-style}) clases tenían 26 | el mismo tipo: \structure{\textless type 'instance' \textgreater}. 27 | Las clases \textit{new-style} unifican clase y tipo — dicho de otra 28 | forma: una clase \textit{new-style} no es sino un tipo definido por 29 | el usuario. 30 | \end{justify} 31 | \end{frame} 32 | 33 | \begin{frame}{00. Heredando de object: ejemplo} 34 | \small 35 | \pythoncode{./code/00/01-old-style-example.py} 36 | \pythonoutput{./code/00/output/01-old-style-example} 37 | \end{frame} 38 | 39 | \begin{frame}{00. La vida antes de Python 2.2} 40 | \begin{alertblock}{} 41 | \centering Pero no es una cuestión sólo de qué devuelve \structure{type()} 42 | \end{alertblock} 43 | 44 | \small 45 | \begin{itemize} 46 | \item No existía \structure{super()...} 47 | \item ... ni los descriptores... 48 | \item ... ni \structure{\_\_slots\_\_} 49 | \item El MRO (\textit{Method Resolution Order}) era mucho más simple. 50 | \item Las clases podían ser lanzadas, sin heredar de \structure{Exception}. 51 | \end{itemize} 52 | 53 | \small 54 | \begin{block}{\centering Old style and new style classes in Python} 55 | \centering \url{https://stackoverflow.com/a/19950198/184363} 56 | \end{block} 57 | \end{frame} 58 | 59 | \begin{frame}{00. Lanzando una clase \textit{new-style}} 60 | \pythoncode{./code/00/02-new-style-raise.py} 61 | \vspace{0.5cm} 62 | \footnotesize 63 | \pythonoutput{./code/00/output/02-new-style-raise} 64 | \end{frame} 65 | 66 | \begin{frame}{00. Lanzando una clase \textit{old-style}} 67 | \pythoncode[fontsize=\normalsize]{./code/00/03-old-style-raise.py} 68 | \vspace{0.5cm} 69 | \footnotesize 70 | \pythonoutput{./code/00/output/03-old-style-raise} 71 | \end{frame} 72 | 73 | \begin{frame}{00. Heredando de object (new-style)} 74 | \begin{itemize} 75 | \item Por compatibilidad, las clases siguen siendo 76 | \textit{old-style} por defecto. 77 | \item En Python 3 las clases \textit{old-style} han desaparecido — 78 | heredar de \structure{object} es opcional. 79 | \item El resumen es que tenemos que heredar siempre de 80 | \structure{object} (o de otra clase \textit{new-style}, claro). 81 | \end{itemize} 82 | 83 | \begin{alertblock}{\centering Moraleja} 84 | \centering Hay que heredar de \structure{object} \emph{siempre} 85 | \end{alertblock} 86 | \end{frame} 87 | -------------------------------------------------------------------------------- /[2015] Dijkstra is My Shepherd, I Lack Nothing/README.rst: -------------------------------------------------------------------------------- 1 | The slides, in Spanish, of the talk I gave at `PyCon ES 2015 `_ (Valencia, Spain). 2 | 3 | |PDF|_ 4 | 5 | * Title: *Dijkstra is my shepherd, I lack nothing* 6 | * Language: Spanish 7 | * License: `CC BY-SA 4.0 `_ 8 | 9 | .. |PDF| image:: ./pics/portada.png 10 | .. _PDF: ./python-dijkstra.pdf 11 | -------------------------------------------------------------------------------- /[2015] Dijkstra is My Shepherd, I Lack Nothing/pics/portada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2015] Dijkstra is My Shepherd, I Lack Nothing/pics/portada.png -------------------------------------------------------------------------------- /[2015] Dijkstra is My Shepherd, I Lack Nothing/python-dijkstra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2015] Dijkstra is My Shepherd, I Lack Nothing/python-dijkstra.pdf -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/README.rst: -------------------------------------------------------------------------------- 1 | The Jupyter notebook of my talk at `EuroPython 2016 `_ (Bilbao, Spain). 2 | 3 | |Notebook|_ 4 | 5 | * Title: *Kung Fu at Dawn with Itertools* 6 | * Language: English 7 | * License: `CC BY-SA 4.0 `_ 8 | 9 | .. |Notebook| image:: ./images/Front_Kalaripayattu.jpg 10 | .. _Notebook: http://nbviewer.jupyter.org/github/vterron/EuroPython-2016/blob/master/kung-fu-itertools.ipynb 11 | -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/804f593851328b126f24e1c4ec386451a5bef09b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/804f593851328b126f24e1c4ec386451a5bef09b.png -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Battle_Cry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Battle_Cry.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Bruce_Lee_Statue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Bruce_Lee_Statue.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Bulletproof_Bruce_Lee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Bulletproof_Bruce_Lee.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Dashi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Dashi.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Deflected_Kick.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Deflected_Kick.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Front_Kalaripayattu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Front_Kalaripayattu.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Shi_DeRu_and_Shi_DeYang.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Shi_DeRu_and_Shi_DeYang.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Steven_Ho_540_Kick.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Steven_Ho_540_Kick.jpg -------------------------------------------------------------------------------- /[2016] Kung Fu at Dawn with Itertools/images/Wushu_Dao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] Kung Fu at Dawn with Itertools/images/Wushu_Dao.jpg -------------------------------------------------------------------------------- /[2016] The Closures that Moved Spielberg/Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] The Closures that Moved Spielberg/Front.jpg -------------------------------------------------------------------------------- /[2016] The Closures that Moved Spielberg/README.md: -------------------------------------------------------------------------------- 1 | The slides of the talk I gave with [Pablo Galindo](https://twitter.com/pyblogsal) at [PyConES 2016](http://2016.es.pycon.org/) (Almería, Spain). 2 | 3 | [![Front slide](./Front.jpg)](./python-closures.pdf) 4 | 5 | - **Title**: *The closures that moved Spielberg* 6 | - **Language**: English 7 | - **License**: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 8 | -------------------------------------------------------------------------------- /[2016] The Closures that Moved Spielberg/python-closures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2016] The Closures that Moved Spielberg/python-closures.pdf -------------------------------------------------------------------------------- /[2018] 'is' versus == [lightning]/Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] 'is' versus == [lightning]/Front.jpg -------------------------------------------------------------------------------- /[2018] 'is' versus == [lightning]/README.md: -------------------------------------------------------------------------------- 1 | The Jupyter notebook of my lighting talk at [PyConES 2018](https://2018.es.pycon.org/) (Málaga, Spain). You can [view it online with nbviewer][nbviewer]. 2 | 3 | [![Front slide](./Front.jpg)][nbviewer] 4 | 5 | - **Title**: *`is` versus `==`* 6 | - **Language**: English 7 | - **License**: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 8 | 9 | [nbviewer]: http://nbviewer.jupyter.org/github/vterron/python-talks/blob/master/%5B2018%5D%20'is'%20versus%20%3D%3D%20%5Blightning%5D/is-versus-equals.ipynb 10 | -------------------------------------------------------------------------------- /[2018] Hashable Objects/Makefile: -------------------------------------------------------------------------------- 1 | #SHELL := /bin/bash 2 | 3 | NOTEBOOK_FILE=python-hashable.ipynb 4 | 5 | # Find out the module we need for the HTTP server, depending on the Python 6 | # version. [Source: https://stackoverflow.com/a/4933395] 7 | PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1))) 8 | PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}) 9 | MODULE.PYTHON.2 := SimpleHTTPServer 10 | MODULE.PYTHON.3 := http.server 11 | 12 | .PHONY: all slides present clean 13 | 14 | all : slides 15 | 16 | slides: ${NOTEBOOK_FILE} 17 | ./slideshow.py ${NOTEBOOK_FILE} 18 | 19 | present: slides 20 | # Binding to port 0 asks the kernel to allocate us a free port. 21 | python -m ${MODULE.PYTHON.${PYTHON_VERSION_MAJOR}} 0 22 | 23 | abridged: ${NOTEBOOK_FILE} 24 | ./slideshow.py ${NOTEBOOK_FILE} --alternative 25 | 26 | clean: 27 | rm -fv *html 28 | -------------------------------------------------------------------------------- /[2018] Hashable Objects/README.md: -------------------------------------------------------------------------------- 1 | **URL:** [vterron.xyz/hash](http://vterron.xyz/hash) 2 | 3 | The Jupyter notebook of my talk on hashable objects. 4 | 5 | There are two versions of the slides: 6 | 7 | - The original, [director's cut](https://en.wikipedia.org/wiki/Director's_cut) version (~1:30h). 8 | * I presented this at [PyDay Tenerife 2018](https://pythoncanarias.es/events/pydaytf18/) (Tenerife, Spain). 9 | * You can view these online [with nbviewer][nbviewer]. 10 | * Talk recording on YouTube is available [here](https://www.youtube.com/watch?v=aU7MEtgdHw0). 11 | * To generate these slides, just run `make`. 12 | - The abridged version (~40m). 13 | * I presented this at [PyConES 2019](https://2019.es.pycon.org/) (Alicante, Spain). 14 | * To generate these slides, run `make abridged`. 15 | 16 | [![Front slide](./images/Cover.jpg)][nbviewer] 17 | 18 | - **Title**: *Hashable Objects* 19 | - **Language**: English 20 | - **License**: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 21 | 22 | [nbviewer]: http://nbviewer.jupyter.org/github/vterron/python-talks/blob/master/%5B2018%5D%20Hashable%20Objects/python-hashable.ipynb 23 | -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/Caravan_in_the_desert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/Caravan_in_the_desert.jpg -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/Cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/Cover.jpg -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/adventure-arid-barren-206724.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/adventure-arid-barren-206724.jpg -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/backlit-dawn-desert-998649.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/backlit-dawn-desert-998649.jpg -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/dawn-desert-dunes-69794.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/dawn-desert-dunes-69794.jpg -------------------------------------------------------------------------------- /[2018] Hashable Objects/images/rhodes-mighty-dict.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Hashable Objects/images/rhodes-mighty-dict.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/Makefile: -------------------------------------------------------------------------------- 1 | #SHELL := /bin/bash 2 | 3 | NOTEBOOK_FILE=python-heaps-ters.ipynb 4 | NBCONVERT_OPTS=--SlidesExporter.reveal_transition=none 5 | 6 | # Find out the module we need for the HTTP server, depending on the Python 7 | # version. [Source: https://stackoverflow.com/a/4933395] 8 | PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1))) 9 | PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}) 10 | MODULE.PYTHON.2 := SimpleHTTPServer 11 | MODULE.PYTHON.3 := http.server 12 | 13 | .PHONY: all slides present clean 14 | 15 | all : slides 16 | 17 | slides: ${NOTEBOOK_FILE} 18 | jupyter nbconvert ${NOTEBOOK_FILE} --to slides ${NBCONVERT_OPTS} 19 | 20 | present: slides 21 | # Binding to port 0 asks the kernel to allocate us a free port. 22 | python -m ${MODULE.PYTHON.${PYTHON_VERSION_MAJOR}} 0 23 | 24 | clean: 25 | rm -fv *html 26 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/README.md: -------------------------------------------------------------------------------- 1 | The Jupyter notebook of my talk at [PyConES 2018](https://2018.es.pycon.org/) (Málaga, Spain). You can [view it online with nbviewer][nbviewer]. 2 | 3 | [![Front slide](./images/cover.jpg)][nbviewer] 4 | 5 | - **Title**: *Python Heaps(ters)* 6 | - **Language**: English 7 | - **License**: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 8 | 9 | [nbviewer]: http://nbviewer.jupyter.org/github/vterron/python-talks/blob/master/%5B2018%5D%20Python%20Heaps-ters/python-heaps-ters.ipynb 10 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/adult-agreement-beard-541526.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/adult-agreement-beard-541526.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/adult-beard-blur-551657.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/adult-beard-blur-551657.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/adult-beard-boy-573564.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/adult-beard-boy-573564.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/adult-beard-businessman-401685.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/adult-beard-businessman-401685.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/beard-corporate-facial-hair-556962.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/beard-corporate-facial-hair-556962.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/binary-heap-with-array-implementation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/binary-heap-with-array-implementation.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Python Heaps-ters/images/cover.jpg -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/04-last-node-becomes-root.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 7 16 | 17 | 18 | 2 19 | 20 | 2 21 | 22 | 23 | R->2 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 2->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 2->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/05-highlight-left-child.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 7 16 | 17 | 18 | 2 19 | 20 | 2 21 | 22 | 23 | R->2 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 2->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 2->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/06-highlight-right-child.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 7 16 | 17 | 18 | 2 19 | 20 | 2 21 | 22 | 23 | R->2 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 2->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 2->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/07-mark-left-child.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 7 16 | 17 | 18 | 2 19 | 20 | 2 21 | 22 | 23 | R->2 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 2->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 2->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/08-swap-root-and-left-child.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 7 19 | 20 | 7 21 | 22 | 23 | R->7 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 7->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 7->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/09-clear-left-child.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 7 19 | 20 | 7 21 | 22 | 23 | R->7 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 7->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 7->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/10-highlight-left-grandchild.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 7 19 | 20 | 7 21 | 22 | 23 | R->7 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 7->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 7->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/11-highlight-right-grandchild.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 7 19 | 20 | 7 21 | 22 | 23 | R->7 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 7->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 7->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/12-mark-right-grandchild.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 7 19 | 20 | 7 21 | 22 | 23 | R->7 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 7->9 44 | 45 | 46 | 47 | 48 | 4 49 | 50 | 4 51 | 52 | 53 | 7->4 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/13-swap-root-and-right-grandchild.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 4 19 | 20 | 4 21 | 22 | 23 | R->4 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 4->9 44 | 45 | 46 | 47 | 48 | 7 49 | 50 | 7 51 | 52 | 53 | 4->7 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/14-clear-right-grandchild.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 4 19 | 20 | 4 21 | 22 | 23 | R->4 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 4->9 44 | 45 | 46 | 47 | 48 | 7 49 | 50 | 7 51 | 52 | 53 | 4->7 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/deletion/15-clear-original-root.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 4 19 | 20 | 4 21 | 22 | 23 | R->4 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 4->9 44 | 45 | 46 | 47 | 48 | 7 49 | 50 | 7 51 | 52 | 53 | 4->7 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/insertion/00-simple-heap-empty-slot.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 4 19 | 20 | 4 21 | 22 | 23 | R->4 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 4->9 44 | 45 | 46 | 47 | 48 | 7 49 | 50 | 7 51 | 52 | 53 | 4->7 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 5->L 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/images/insertion/01a-highlight-next-free-slot.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | R 14 | 15 | 2 16 | 17 | 18 | 4 19 | 20 | 4 21 | 22 | 23 | R->4 24 | 25 | 26 | 27 | 28 | 5 29 | 30 | 5 31 | 32 | 33 | R->5 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 9 41 | 42 | 43 | 4->9 44 | 45 | 46 | 47 | 48 | 7 49 | 50 | 7 51 | 52 | 53 | 4->7 54 | 55 | 56 | 57 | 58 | 8 59 | 60 | 8 61 | 62 | 63 | 5->8 64 | 65 | 66 | 67 | 68 | L 69 | 70 | 71 | 72 | 5->L 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /[2018] Python Heaps-ters/lots-of-numbers.txt: -------------------------------------------------------------------------------- 1 | 35 2 | 38 3 | 31 4 | 2 5 | 12 6 | 27 7 | 6 8 | 5 9 | 4 10 | 39 11 | 28 12 | 10 13 | 46 14 | 40 15 | 42 16 | 21 17 | 45 18 | 49 19 | 19 20 | 16 21 | 26 22 | 41 23 | 7 24 | 22 25 | 24 26 | 30 27 | 17 28 | 8 29 | 0 30 | 33 31 | 11 32 | 13 33 | 48 34 | 25 35 | 32 36 | 43 37 | 29 38 | 9 39 | 3 40 | 15 41 | 47 42 | 36 43 | 37 44 | 20 45 | 1 46 | 34 47 | 44 48 | 14 49 | 23 50 | 18 51 | -------------------------------------------------------------------------------- /[2018] Taking the Garbage Out/Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Taking the Garbage Out/Front.jpg -------------------------------------------------------------------------------- /[2018] Taking the Garbage Out/README.md: -------------------------------------------------------------------------------- 1 | The slides of the talk I gave with [Pablo Galindo](https://twitter.com/pyblogsal) at [PyConES 2018](https://2018.es.pycon.org/) (Málaga, Spain). 2 | 3 | [![Front slide](./Front.jpg)](./python-garbage-collection.pdf) 4 | 5 | - **Title**: *Python: Taking the Garbage Out* 6 | - **Language**: English 7 | - **License**: [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 8 | 9 | -------------------------------------------------------------------------------- /[2018] Taking the Garbage Out/python-garbage-collection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vterron/python-talks/ebe86876bddba33916335bb3d8c3d9967b51ea54/[2018] Taking the Garbage Out/python-garbage-collection.pdf --------------------------------------------------------------------------------