Skip to content

Commit

Permalink
Create first version of dataclass examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Richter committed Nov 24, 2019
1 parent 74148da commit 2a6b48f
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 2 deletions.
19 changes: 19 additions & 0 deletions 01_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
Ukázka vytvoření objektu z běžné třídy
Pro inicializaci se využívá dunder (double underscore) metoda __init__()
Dunder metody nemá smysl ve většině případů volat přímo, ale jsou volány Python interpretem
při nějaké události. V případě metody __init__() je události vytvoření instance třídy Person
"""

# Třída Person
class Person:
def __init__(self, name, surname, age, height):
self.name = name
self.surname = surname
self.age = age
self.height = height


# Vytvoření instance třídy Person
person = Person("John", "Doe", 66, 180)
print(person)
23 changes: 23 additions & 0 deletions 02_repr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
Ukázka implementace reprezentace vyplnění dunder metody __repr__()
Ve chvíli, kdy se instance třídy Person dá "vypsat" funkcí print, zavolá se dunder metoda
__repr__(), která printu předá to, co jsme si nadefinovali.
"""


class Person:
def __init__(self, name, surname, age, height):
self.name = name
self.surname = surname
self.age = age
self.height = height

def __repr__(self):
return f"class: {self.__class__.__name__}," \
f" name: {self.name}, surname: {self.surname}, age: {self.age}, height: {self.height}"


person = Person("John", "Doe", 66, 180)
print(person)

65 changes: 65 additions & 0 deletions 03_lt_eq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
Ukázka implementace reprezentace vyplnění dunder metody __repr__()
Funguje to obdobně jako u __repr__()
Dunder metody jsou volány při porovnávání instancí příslušnými operátory
__eq__() ==
__ne__() !=
__gt__() >
__lt__() <
__ge__() >=
__le__() <=
V příkladu jsou některé zakomentované. Je to z důvodu, že ve skutečnosti všechny nejsou třeba.
Python si dokáže odvodit opačnou funkci. Např. z __eq__ si odvodí __ne__
"""

class Person:
def __init__(self, name, surname, age, height):
self.name = name
self.surname = surname
self.age = age
self.height = height

def __repr__(self):
return f"class: {self.__class__.__name__}," \
f" name: {self.name}, surname: {self.surname}, age: {self.age}, height: {self.height}"

def __eq__(self, other):
return (self.name, self.surname, self.age, self.height) == \
(other.name, other.surname, other.age, other.height)

def __lt__(self, other):
return ((self.name, self.surname, self.age, self.height) <
(other.name, other.surname, other.age, other.height))

def __ge__(self, other):
return ((self.name, self.surname, self.age, self.height) >=
(other.name, other.surname, other.age, other.height))

# def __ne__(self, other):
# return (self.name, self.surname, self.age, self.height) != \
# (other.name, other.surname, other.age, other.height)

# def __le__(self, other):
# return ((self.name, self.surname, self.age, self.height) <=
# (other.name, other.surname, other.age, other.height))

# def __gt__(self, other):
# return ((self.name, self.surname, self.age, self.height) >
# (other.name, other.surname, other.age, other.height))


john = Person("John", "Doe", 66, 180)
john_copy = Person("John", "Doe", 66, 180)
great_zohn = Person("Zohn", "Zow", 666, 1800)

print(f"{john}\n{john_copy}\njohn == john_copy: {john == john_copy}\n")
print(f"{john}\n{great_zohn}\njohn == great_zohn: {john == great_zohn}\n")
print(f"{john}\n{great_zohn}\njohn < great_zohn: {john < great_zohn}\n")





32 changes: 32 additions & 0 deletions 04_dataclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Doteď by nám příklady fungovaly i na starším Pythonu. Nyní je již třeba minimálně verze 3.7.
Příklad ukazuje sílu datových tříd, kdy nemusíme implementovat žádné dunder metody pro inicializaci,
reprezentaci ani porovnání, vše je za nás vytvořeno.
"""

from dataclasses import dataclass

"""
Datová třída se vytváří použitím dekorátoru @dataclass (v tomto konkrétním příkladu s parametrem
order=True). Dekorátor jsme si naimportovali z modulu dataclassses, který je součástí interpretu,
viz. výše.
name:str Toto je tzv. typová anotace, která Pythonu řekne, o jaký datový typ se jedná (v tomto
konkrétním případě o řetězec). Tuto informaci potřebuje pro potřeby porovnávání.
"""
@dataclass(order=True)
class Person:
name: str
surname: str
age: int
height: int


john = Person("John", "Doe", 66, 180)
john_copy = Person("John", "Doe", 66, 180)
great_zohn = Person("Zohn", "Zow", 666, 1800)

print(f"{john}\n{john_copy}\njohn == john_copy: {john == john_copy}\n")
print(f"{john}\n{great_zohn}\njohn == great_zohn: {john == great_zohn}\n")
print(f"{john}\n{great_zohn}\njohn < gret_zohn: {john < great_zohn}\n")
24 changes: 24 additions & 0 deletions 05_decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Ukázka vytvoření vlastního deokorátoru
"""

def world(function):
def wrapper():
return function() + "world!"
return wrapper


def hi():
return "Hi "

# Takhle by vypadalo použití dekorátoru v případě, že by neexistovala syntaxe s @ - viz. níže
decorated_hi = world(hi)
print(decorated_hi())

# Standardní použití námi vytvořeného dekorátoru
@world
def hello():
return "Hello "


print(hello())
26 changes: 26 additions & 0 deletions 06_dataclass_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Tento příklad ukazuje, jak datové třídy podrobněji nastavovat. V předchozích příkladech
nám do porovnávání či reprezentace vstupovali veškeré atributy třídy. Tady si ukážeme, jak můžeme
některé vynechat, nebo jak nastavit implicitní hodnoty.
"""

from dataclasses import dataclass, field


@dataclass(order=True)
class Person:
name: str = field(compare=False, default="John")
surname: str = field(compare=False, default="Dow")
age: int = field(repr=False, default=66)
height: int = field(compare=False, repr=False, default=180)


john = Person()
john_bad_copy = Person(surname="Doh")
great_zohn = Person("Zohn", "Zow", 10, 1800)

print(f"{john}\n{john_bad_copy}\njohn == john_bad_copy: {john == john_bad_copy}\n")
print(f"{john}\n{great_zohn}\njohn == great_zohn: {john == great_zohn}\n")
print(f"{john}\n{great_zohn}\njohn < great_zohn: {john < great_zohn}\n")


36 changes: 36 additions & 0 deletions 07_dataclass_frozen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
Ukázka parametru frozen - zajistí nám, že vytvořené instance již nepůjdou dále měnit.
"""

from dataclasses import dataclass



@dataclass
class HotJohn:
name: str = "John"
surname: str = "Doe"
age: int = 66
height: int = 180


@dataclass(frozen=True)
class FrozenJohn:
name: str = "John"
surname: str = "Doe"
age: int = 66
height: int = 180


hot_john = HotJohn()
frozen_john = FrozenJohn()

print(hot_john)
hot_john.height = 170
hot_john.surname = "Doh"
hot_john.weight = 80
print(hot_john)
print(hot_john.weight)

frozen_john.height = 80
frozen_john.weight = 80
31 changes: 31 additions & 0 deletions 08_dataclass_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
Ukázka všech parametrů, které můžeme při vytvoření datové třídy využít.
order - defaultně False, při zapnutí se implementuje metody __lt__, __gt__, __eg__, __el__
eq - defaultně True, při zapnutí implementuje metody __eq__, __ne__
init - defaultně True, implementuje __init__ metodu
repr - defaultně True, implementuje __repr__ metodu
frozen - defaultně False, při zapnutí nám nedovolí vytvořenou instanci měnit
unsafe_hash - Nebudeme vysvětlovat, protože se jedná o složitější koncept a není
pravděpodobné, že bychom jej opravdu potřebovali. Zjednodušeně řečeno, ovlivňuje zda bude
implementována dunder metoda __hash__.
Pozor, neovlivňuje to sám, ale vždy jde o kombinaci parametrů order, frozen, unsafe_hash.
"""

from dataclasses import dataclass, field


@dataclass(order=True, frozen=False, unsafe_hash=False, init=True, eq=True, repr=True)
class Person:
name: str = field(compare=False, default="John")
surname: str = field(compare=False, default="Doe")
age: int = field(repr=False, default=66)
height: int = field(compare=False, repr=False, default=180)


john = Person()
john_bad_copy = Person(surname="Doh")
great_zohn = Person("Zohn", "Zow", 10, 1800)

print(f"{john}\n{john_bad_copy}\njohn == john_bad_copy: {john == john_bad_copy}\n")
print(f"{john}\n{great_zohn}\njohn == great_zohn: {john == great_zohn}\n")
print(f"{john}\n{great_zohn}\njohn < great_zohn: {john < great_zohn}\n")
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# pyvo-hk-dataclasses
Ukázka použití datových tříd v Pythonu 3.7
# Datové třídy z Pythonu 3.7

Projekt obsahuje jednoduché příklady demonstrující výhody využití datových tříd.
Příklady na sebe logicky navazují, v každém dalším je představena nová funkcionalita.
Proto je dobré začít od 01_init.py

Pro funkčnost ukázek je potřeba Python verze 3.7 nebo vyšší.

0 comments on commit 2a6b48f

Please sign in to comment.