Type hints w jzyku Python Konrad Haas 4Developers 2018 Plan type - - PowerPoint PPT Presentation

type hints w j zyku python
SMART_READER_LITE
LIVE PREVIEW

Type hints w jzyku Python Konrad Haas 4Developers 2018 Plan type - - PowerPoint PPT Presentation

Type hints w jzyku Python Konrad Haas 4Developers 2018 Plan type hints dlaczego? skadnia narzdzia biblioteki projekty legacy def notify_everyone (items): for item in items: item.owner.notify() def cancel_all (items):


slide-1
SLIDE 1

Type hints w języku Python

Konrad Hałas

4Developers 2018

slide-2
SLIDE 2
slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5
slide-6
SLIDE 6

Plan

type hints dlaczego? składnia narzędzia biblioteki projekty legacy

slide-7
SLIDE 7

def notify_everyone(items): for item in items: item.owner.notify()

slide-8
SLIDE 8

def cancel_all(items): notify_everyone(items) ...

slide-9
SLIDE 9

Rozwiązania

dokumentacja zewnętrzna dokumentacja w kodzie (RST, epytext, NumPy, Google) przepisać wszystko do języka statycznie typowanego

slide-10
SLIDE 10
slide-11
SLIDE 11

def count_unique_words(text, case_sensitive): ...

slide-12
SLIDE 12

def count_unique_words(text: str, case_sensitive: bool) ‑> int: ...

slide-13
SLIDE 13

def median(values: list) ‑> float: ...

slide-14
SLIDE 14

from typing import List def median(values: List[float]) ‑> float: ...

slide-15
SLIDE 15

from typing import Dict def count_chars(text: str) ‑> Dict[str, int]: ...

slide-16
SLIDE 16

from typing import List class Point: ... def calculate_area(vertices: List[Point]) ‑> float: ...

slide-17
SLIDE 17

from typing import Optional def total_amount(order: Order, discount: Optional[Discount]) ‑> Money: ...

slide-18
SLIDE 18

from typing import List, Union def send_confirmation(email: Union[str, List[str]]) ‑> None: ...

slide-19
SLIDE 19

from typing import Any def get_most_frequent(items: list) ‑> Any: ...

slide-20
SLIDE 20

from typing import List, TypeVar T = TypeVar('T') def get_most_frequent(items: List[T]) ‑> T: ...

slide-21
SLIDE 21
slide-22
SLIDE 22

from typing import List class Item: ... class Basket: def __init__(self): self.items: List[Item] = [] def add_item(self, item: Item): self.items.append(item)

slide-23
SLIDE 23

Narzędzia

mypy PyCharm ...

slide-24
SLIDE 24

def total_price(items: List[Item], discount: Optional[float] = None) ‑> float: ...

slide-25
SLIDE 25

def total_price(items: List[Item], discount: Optional[float] = None) ‑> float: result = 0.0 for item in items: result += item.count * item.product.price result ‑= discount return result

slide-26
SLIDE 26

def total_price(items: List[Item], discount: Optional[float] = None) ‑> float: result = 0.0 for item in items: result += item.count * item.product.price result ‑= discount return result $ mypy ‑‑strict example.py example.py:9: error: "Item" has no attribute "count" example.py:10: error: Unsupported operand types for ‑ ("float" and "Optional[float]")

slide-27
SLIDE 27

def total_price(items: List[Item], discount: Optional[float] = None) ‑> float: result = 0.0 for item in items: result += item.quantity * item.product.price if discount: result ‑= discount return result $ mypy ‑‑strict example.py

slide-28
SLIDE 28
slide-29
SLIDE 29
slide-30
SLIDE 30

Biblioteki

injector dacite ...

slide-31
SLIDE 31

def register_user(user_details: UserDetails): ...

slide-32
SLIDE 32

from users.repositories import UsersRepository def register_user(user_details: UserDetails): ... repository = UsersRepository() repository.create_user(...)

slide-33
SLIDE 33

class UsersService: def __init__(self, repository: UsersRepository): self.repository = repository def register_user(self, user_details: UserDetails): ... self.repository.create_user(...)

slide-34
SLIDE 34

class UsersRepository: def __init__(self, data_base: DataBase): self.data_base = data_base def create_user(self, user: User): ... self.data_base.insert(...)

slide-35
SLIDE 35

class DataBase: def __init__(self, session: DataBaseSession): self.session = session ...

slide-36
SLIDE 36

session = DataBaseSession(...) data_base = DataBase(session) users_repository = UsersRepository(data_base) users_service = UsersService(users_repository)

slide-37
SLIDE 37

class DataBaseSession: ... class DataBase: def __init__(self, session: DataBaseSession): ... class UsersRepository: def __init__(self, database: DataBase): ... class UsersService: def __init__(self, repository: UsersRepository): ...

slide-38
SLIDE 38

from injector import inject class DataBaseSession: ... class DataBase: @inject def __init__(self, session: DataBaseSession): ... class UsersRepository: @inject def __init__(self, database: DataBase): ... class UsersService: @inject def __init__(self, repository: UsersRepository): ...

slide-39
SLIDE 39

from injector import Injector users_service = Injector().get(UsersService)

slide-40
SLIDE 40

from dataclasses import dataclass @dataclass class User: name: str age: int is_active: bool user = User(name='John', age=30, is_active=True)

slide-41
SLIDE 41

import dacite data = { 'name': 'John', 'age': 30, 'is_active': True, } user = dacite.from_dict(data_class=User, data=data) assert user == User(name='John', age=30, is_active=True)

slide-42
SLIDE 42

Type hints w projekcie legacy

gradual typing statyczna analiza uruchamiana w ramach CI wymuszanie type annotations dla: kluczowych modułów interfejsów

slide-43
SLIDE 43

Podsumowanie

zrozumiały kod mniej błędów nowe możliwości

slide-44
SLIDE 44

Dziękuję!

@konradhalas / konradhalas.pl

slide-45
SLIDE 45

Zdjęcia

Jacek Kołodziej ‑ http://kolodziejj.info/ Korsan Studio ‑ http://facebook.com/korsanstudio

slide-46
SLIDE 46

Narzędzia/biblioteki

mypy ‑ http://mypy‑lang.org PyCharm ‑ https://www.jetbrains.com/pycharm dacite ‑ https://github.com/konradhalas/dacite injector ‑ https://github.com/alecthomas/injector