Practical uses for. Function Annotations. Manuel Ceron

Similar documents
GRADUAL TYPING OF PRODUCTION APPLICATIONS ŁUKASZ LANGA

Python 3000 and You. Guido van Rossum PyCon March 14, 2008

Using Type Annotations in Python. by Philippe Fremy / IDEMIA

WHY YOU DON'T NEED DESIGN PATTERNS IN PYTHON? EuroPython 2017

Part I. Wei Tianwen. A Brief Introduction to Python. Part I. Wei Tianwen. Basics. Object Oriented Programming

CIS192 Python Programming. Robert Rand. August 27, 2015

Python 3000 and You. Guido van Rossum EuroPython July 7, 2008

CS 11 python track: lecture 3. n Today: Useful coding idioms

Design and implementation of a RPC library in python

Python Type Checking Guide Documentation

ECE 364 Software Engineering Tools Laboratory. Lecture 7 Python: Object Oriented Programming

The current topic: Python. Announcements. Python. Python

Not-So-Mini-Lecture 6. Modules & Scripts

APT Session 2: Python

CSC148: Week 1

django-crucrudile Documentation

8. The C++ language, 1. Programming and Algorithms II Degree in Bioinformatics Fall 2017

Friday, 11 April 14. Advanced methods for creating decorators Graham Dumpleton PyCon US - April 2014

python 01 September 16, 2016

Objects. say something to express one's disapproval of or disagreement with something.

A simple interpreted language

Python for C programmers

Iterators & Generators

Object Model Comparisons

Outline. Simple types in Python Collections Processing collections Strings Tips. 1 On Python language. 2 How to use Python. 3 Syntax of Python

7. (2 pts) str( str( b ) ) str '4' will not compile (single, double, or triple quotes

COLUMNS. Thinking about Type Checking

New York University School of Continuing and Professional Studies Management and Information Technology. Advanced Python. Homework, Session 5

Functions!!! Why functions? Functions provide good way to design systems!

Python for Non-programmers

Introduction to Computer Science. Course Goals. Python. Slides02 - Intro to Python.key - September 15, 2015

Python: common syntax

Beyond Blocks: Python Session #1

CIS192: Python Programming

COM S 213 PRELIM EXAMINATION #2 April 26, 2001

Overloading. F21SC Industrial Programming: Python: Advanced Language Features. Overloading. Overloading arithmetic operations

tolerance Documentation

Exercise: The basics - variables and types

Types, lists & functions

Built-in functions. You ve used several functions already. >>> len("atggtca") 7 >>> abs(-6) 6 >>> float("3.1415") >>>

Try and Error. Python debugging and beautification

Data Structures. Lists, Tuples, Sets, Dictionaries

Python Programming: Lecture 2 Data Types

2. First Program Stuff

TABLE OF CONTENTS 2 CHAPTER 1 3 CHAPTER 2 4 CHAPTER 3 5 CHAPTER 4. Algorithm Design & Problem Solving. Data Representation.

A brief introduction to C programming for Java programmers

CS2304: Python for Java Programmers. CS2304: Sequences and Collections

C Program Development and Debugging under Unix SEEM 3460

Flow Control: Branches and loops

Abstract Data Types. CS 234, Fall Types, Data Types Abstraction Abstract Data Types Preconditions, Postconditions ADT Examples

Overloading. F21SC Industrial Programming: Python: Advanced Language Features. Overloading. Overloading arithmetic operations

Imagination Documentation

Getting Started with Python

User Defined Types. Babes-Bolyai University Lecture 06. Lect Phd. Arthur Molnar. User defined types. Python scope and namespace

5/3/2006. Today! HelloWorld in BlueJ. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont. HelloWorld in BlueJ, Cont.

A Problem. Loop-Body Returns. While-Loop Solution with a Loop-Body Return. 12. Logical Maneuvers. Typical While-Loop Solution 3/8/2016

Short Notes of CS201

CME 193: Introduction to Scientific Python Lecture 4: Strings and File I/O

Intro. Classes & Inheritance

Black Problem 2: Huffman Compression [75 points] Next, the Millisoft back story! Starter files

12. Logical Maneuvers. Topics: Loop-Body Returns Exceptions Assertions Type Checking Try-Except

BASIC COMPUTATION. public static void main(string [] args) Fundamentals of Computer Science I

Python debugging and beautification

Compsci 101 Fall 2015 Exam 1 Rubric. Problem 1 (24 points)

CNRS ANF PYTHON Objects everywhere

redis-lua Documentation

CS201 - Introduction to Programming Glossary By

CS 1301 Exam 2 Fall 2013

The reader is referred to the Objective Caml reference manual for a more detailed description of these features.

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

GIS 4653/5653: Spatial Programming and GIS. More Python: Statements, Types, Functions, Modules, Classes

Page. User. Sorting Mini-HOW TO. Search Titles Text. More Actions: HowTo Sorting. HowTo/Sorting

Overview of OOP. Dr. Zhang COSC 1436 Summer, /18/2017

Programming Languages

Introduction to Python Code Quality

Key Differences Between Python and Java

CS-141 Final Exam Review December 8, 2017 Presented by the RIT Computer Science Community

Next: What s in a name? Programming Languages. Data model in functional PL. What s in a name? CSE 130 : Fall Lecture 13: What s in a Name?

CMSC 330: Organization of Programming Languages. Rust Basics

Review Sheet for Midterm #1 COMPSCI 119 Professor William T. Verts

Table of Contents EVALUATION COPY

Compound Data Types 1

Python for Analytics. Python Fundamentals RSI Chapters 1 and 2

SPARK-PL: Introduction

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

CIS192 Python Programming


DevKitchen 2018 Python in Cinema 4D R20

Lecture #15: Generic Functions and Expressivity. Last modified: Wed Mar 1 15:51: CS61A: Lecture #16 1

CS1 Lecture 3 Jan. 18, 2019

DEBUGGING TIPS. 1 Introduction COMPUTER SCIENCE 61A

Lecture 19. Operators and Abstraction

CS115 - Module 4 - Compound data: structures

Introduction to Python

Arrays, Pointers and Memory Management

Downloaded from Chapter 2. Functions

CSC324 Principles of Programming Languages

Lecture 18. Classes and Types

Question 1. tmp = Stack() # Transfer every item from stk onto tmp. while not stk.is_empty(): tmp.push(stk.pop())

University of Washington CSE 140 Introduction to Data Programming Winter Midterm exam. February 6, 2013

Transcription:

Practical uses for Function Annotations Manuel Ceron manuel.ceron@booking.com

About me Colombian developer living in the Netherlands First time at EuroPython Programming Python for 10 years Currently working at Currently hiring www.booking.com/jobs

What are Function Annotations? Syntactic sugar for adding metadata to function definitions def compile(source: "something compilable", filename: "where the compilable thing comes from", mode: "is this a single statement or a suite?"): def greet(name: str, age: int) -> str: return 'Hello {0}, you are {1} years old'.format(name, age) PEP 3107 Python 3.x only First draft since 2006

Annotations are just syntactic sugar: >>> def distance(p1: Point, p2: Point) -> float: return math.sqrt( (p2.x - p1.x)**2 + (p2.y - p1.y)**2 ) >>> distance. annotations {'p2': <class ' main.point'>, 'p1': <class ' main.point'>, 'return': <class 'float'>}

Why this talk Converging static and dynamic typing Potential of optional static typing Why nobody uses this feature

Adding Typing Information def open(filename: str, mode: str, encoding: str = None, buffering: int = -1, closedfd: bool = True) -> IOBase: Why: Help tools to make life easier. Some auto documentation.

Helping tools (IDE, Editor) def authenticate(self, request): request. def authenticate(self, user, password): return user.check_pasword(password): class User: def check_password(password):

Helping tools (IDE, Editor) def authenticate(self, request: HttpRequest): request. def authenticate(self, user: auth.user, password): return user.check_pasword(password): class User: def check_password(password):

Wait a sec! You don't need this if you write Unit Tests It's not about getting the error, but when and how you get it.

Wait a sec! You are missing the point of Duck Typing Duck typing is not incompatible with type annotations More on this later

Wait a sec! Writing types is too verbose Remember: annotations are optional In practice dynamic languages can be very verbose

Libraries usually do this def attach_volume(self, volume_id, instance_id, device): """ Attach an EBS volume to an EC2 instance. :type volume_id: str :param volume_id: The ID of the EBS volume to be attached. :type instance_id: str :param instance_id: The ID of the EC2 instance to which it will be attached. :type device: str :param device: The device on the instance through which the volume will be exposted (e.g. /dev/sdh) :rtype: bool :return: True if successful """ params = {'InstanceId': instance_id, 'VolumeId': volume_id, 'Device': device} return self.get_status('attachvolume', params, verb='post')

Experiment: Runtime checking Probably a very bad idea It's slow ( up to 200x slow) Not very useful Testbed for concepts though Might become useful if we expand the notion of type

Runtime checking: how it looks >>> @typechecked def test(a: int) -> int: return a >>> test(1) 1 >>> test('string') Traceback (most recent call last): TypeError: Incorrect type for "a" Warning: slow code The @typechecked decorator checks arguments and uses isinstance to determine if the they match the annotation

But isinstance is killing duck typing! Or not: >>> class IterableWithLength(Interface): def iter (): pass def len (): pass >>> isinstance([1, 2, 3], IterableWithLength) True >>> isinstance({'one': 1, 'two': 2}, IterableWithLength) True >>> isinstance((x for x in range(10)), IterableWithLength) False >>> isinstance(1, IterableWithLength) False

Another example >>> class Person(Interface): name = str age = int def say_hello(name: str) -> str: pass >>> class Developer: def init (self, name, age): self.name = name self.age = age def say_hello(self, name: str) -> str: return 'hello ' + name >>> isinstance(developer('bill', 20), Person) True

Implementation of structural interfaces: A little bit of python black magic: Metaclasess instancecheck subclasscheck

Types + behaviour = predicates >>> Positive = predicate(lambda x: x > 0) >>> isinstance(1, Positive) True >>> isinstance(0, Positive) False >>> @typechecked def sqrt(n: Positive): >>> sqrt(-1) Traceback (most recent call last): TypeError: Incorrect type for "n"

More fun with predicates >>> FileMode = options('r', 'w', 'a', 'r+', 'w+', 'a+') >>> isinstance('w', FileMode) True >>> isinstance('x', FileMode) False >>> isinstance(true, only(bool)) True >>> isinstance(1, only(bool)) False >>> isinstance(1, optional(int)) True >>> isinstance(none, optional(int)) True >> @predicate def Even(object): return object % 2 == 0 >>> EvenAndPositive = Even & Positive

The open function annotated again def open(filename: FilenameString, mode: options('r', 'w', 'a', 'r+', 'w+', 'a+'), encoding: optional(str) = None, buffering: int = -1, closedfd: bool = True) -> FileInterface:

Unions >>> NumberOrString = union(int, str) >>> isinstance(1, NumberOrString) True >>> isinstance('string', NumberOrString) True >>> issubclass(int, NumberOrString) True >>> issubclass(str, NumberOrString) True def isinstance(object, class_: union(type, tuple)) -> bool:

Function overloading @overload def isinstance(object, t: type): @isinstance.add def isinstance(object, t: tuple): # PEP 443 >>> from functools import singledispatch >>> @singledispatch def fun(arg): print(arg) >>> @fun.register(collections.mutablemapping) def _(arg): for k, v in arg.items(): print(k, '->', 'v')

More kinds of types typedefs: >>> @typedef def EventHandler(event: Event) -> bool: pass >>> def handler(event: MouseEvent) -> bool: print('click') return True >>> isinstance(handler, callback) True >>> isinstance(lambda: True, callback) False typedict({str: int}) typeseq([int]) typeseq(set(int)) typeseq((int,)) Parameterized types

A different approach to type annotations: rightarrow Named types: int, long, float, complex, str, YourClassNameHere, Lists: [int], [[long]], Tuples: (int, long), (float, (int, Regex)), Dictionaries: {string: float}, { (str, str) : [complex] }, Unions: int long float, str file, "Anything goes":?? Functions: str -> int (int) -> int (int, int) -> int ( (int, int) ) -> int ( str file ) -> SomeClass (int, *[str]) -> [(str, int)] (int, *[int], **{int: str}) -> str Objects: object(self_type, field1: int, field2: str, )

Using rightarrow >>> @guard('unicode -> str') def safe_encode(s): return s.encode('utf-8') >>> safe_encode(u'hello') 'hello' >>> safe_encode('\xa3') TypeError: Type check failed:? does not have type unicode >>> def safe_encode(s: str) -> bytes: return s.encode('utf-8') Or better:

Other uses for annotations Documentation: def attach_volume(self, volume_id: "The ID of the EBS volume " "to be attached", instance_id: "EC2 Instance to which it " "will be attached", device: "The device on the instance " "through which the " "volume will be exposed " "(e.g. /dev/sdh) ") -> "True if successful":

Combining different uses of annotations: def compile(source: (str, "something compilable"), filename: (str, "where the compilable thing comes from"), mode: (int, "is this a single statement or a suite?")):

Annotations for language bridges @ctypes_import('libc.strchr') def strchr(s: 'char *', pos: 'short') -> 'char *': pass @sql_insert def strchr(s: 'VARCHAR', pos: 'INTEGER'):

Why annotations are not used? Not a wide know feature Python 3.x only Too much flexibility Some use cases not complete Not immediate benefit

Questions? Meanwhile: typeannotations: https://github.com/ceronman/typeannotations rightarrow: https://github.com/kennknowles/python-rightarrow PEP 3107: http://www.python.org/dev/peps/pep-3107/

Thanks!