Jupyter vs. IDE

Integrated development environment, skrátene IDE je prostredie , lubovolny editor na vyvoj. Vyvijat mozes samozrejme aj v notepade alebo v inom editore, no vyhodou komplexnejsich nastrojov ako je napriklad Atom, PyCharm, Sublime Text je podpora:

  • syntaxe jazyka, v ktorom programujes,
  • moznost lepsieho clenenia kodu,
  • moznost autocomplete roznych funkcii a metod
  • napojenie na dalsie systemy, ako napriklad git, ktory sa stara o verzionovanie kodu
  • ine vyhody...

Jupyter notebook je vhodny nastroj na pracu:
  • s datami,
  • datovu analyzu,
  • spustanie kodu, kedy chceme vidiet vysledok priamo,
  • moznost kod zdielat s niekym inym,
  • moznost vytvarat z jupyteru celkovu analyzu, ktoru nasledne posleme klientovi ako HTML stranku, podpora html syntaxe, grafov, vizualizacii, 3D doplnkov a mnoho ineho.

Ak vsak chceme nasu analyzu a kod zakomponovat do komplexneho projektu akym je napriklad nejaky CMS system, wikipedia, webova, desktopova aplikacia je lepsou volbou pouzit editor, v ktorom kod napiseme. Na druhej strane v editore nie je mozne si data prehliadat, vidiet medzikroky, vykreslovat grafy a podobne. Preto je vhodnou kombinaciou, spravit si datovu analyzu v Jupyteri a nasledne kod exportovat ako python skript a umiestnit na vhodne miesto do programu v editora.

Triedy

Skor ako sa pustime do tried si povieme nieco o objektoch. V Pythone je objektom vsetko, co mozeme ulozit do premennej, vratit vo funkcii alebo metode.

Vlastnosti objektu

Zakladnou vlastnostou objektov je, ze obsahuju:

  • Data - informacie
  • Popis spravania - metody

Priklad Napriklad retazec v Pythone, kde si ulozim svoje meno "Sveta" je tiez objektom, ktory je tvoreny:

  • atributami (informaciami) - sekvencia znakov Sveta
  • metodami, nad retazcom Sveta mozeme pouzit napriklad metodu upper(), ktora zmeni vsetky znaky v retazci na velke. "Sveta".upper() vrati "SVETA"

S retazcom je mozne taktiez pouzit napriklad aj funkciu len(), ktora zrata pocet znakov retazca "Sveta" len("Sveta") vrati nam hodnotu 5. Narozdiel od upper, ktoru vieme pouzit iba nad retazcom, lebo je logicke, ze budeme zvetsovat iba pismena v nejakom slove, funkciu len vieme pouzit aj nad inymi objektami, napriklad nad polom, rovnako ako vieme zratat pocet pismen mena, vieme zratat pocet prvkov pola.

Je potrebne si uvedomit

Data kazdeho objektu su ine a specificke. Retazec "Sveta" obsahuje moje meno, ale napriklad retazec "Richard" uz obsahuje meno ine. Avsak upper() a len() mozeme pouzit rovnako nad retazcami "Sveta", aj "Richard"

Vytvorenie triedy

Najprv si vydefinujeme triedu, ktoru ideme vytvarat:

  • atributy (data)
  • a metody (spravanie)

Predstavme si napriklad ze by sme chceli vytvorit triedu Auto.


Ked sa pozrieme na obrazok auta vidime tam atributy napriklad:

  • farba_auta
  • pocet_kolies
  • povrch_auta
  • typ_auta
  • ma_autopilota
  • cena_auta
  • pocet_kilometrov
  • rok_vyroby
  • priemerna_rychlost
  • posledna_oprava
  • ma_dialnicnu_znamku
  • je_zapnute
  • nazov_auta
  • ....
    Mohli by sme definovat co nas napadne a co od nas aplikacia pozaduje. Teraz si podme vydefinovat metody, ktore s autom vieme robit
  • nastartovat
  • zrychlit
  • spomalit
  • zabrzdit
  • zmenit_cenu
  • upravit_farbu
  • pohnut_sa_dopredu
  • otocit_sa_dolava
  • ....

Taktiez tu mozeme vydefinovat lubovolny pocet metod, podla poziadaviek aplikacie.

Vytvorenie triedy v Pythone

Triedu vytvarame pomocou prikazu Class a nazov triedy.

In [3]:
class Car():
    pass

Pridat metodu show_car_name

Metodu definujeme rovnako ako funkciu cez def. Metoda vyzera presne ako funkcia, len obsahuje navyse v sebe atribut self.

In [4]:
class Car():
    def show_car_name(self):
        print ("Car name is: rapid")

Objekty

Objektom je uz konkretna vec z realneho sveta. V nasom priklade s autami je objektom napriklad konkretne auto skoda rapid, alebo tesla a podobne. Na triedu sa mozeme pozerat ako na predlohu/sablonu, z ktorej vytvarame rozne objekty s rovnakymi vlastnostami a metodami.


Ukazka dalsich objektov z realneho sveta

In [5]:
#inicializacia triedy, vytvorenie objektu skoda_rapid
skoda_rapid = Car()
In [6]:
#volanie metody show_car_name nad objektom skoda_rapid.
skoda_rapid.show_car_name()
Car name is: rapid

Pridanie atributu

Teraz si ideme pridat do nasej triedy auto atributy.
Napriklad atributy:

  • color,
  • car_name
In [7]:
skoda_rapid.color = "red"
skoda_rapid.car_name = "rapid"
In [8]:
print (skoda_rapid.color)
red
In [9]:
print (skoda_rapid.car_name)
rapid

Self

Teraz si povieme nieco o self. Pomocou self ma metoda pristup k objektu, s ktorym prave pracuje. Napriklad vieme spristupnit metodu show_car_name konkretnemu objektu a jeho atributom.


Priklad:

In [10]:
class Car():
    def show_car_name(self):
        print ("Car {} has color: {}".format(self.car_name, self.color))
In [11]:
tesla = Car()
tesla.color = "black"
tesla.car_name = "Tesla model S"
fiat = Car()
fiat.color = "blue"
fiat.car_name = "Fiat V"

tesla.show_car_name()
fiat.show_car_name()
Car Tesla model S has color: black
Car Fiat V has color: blue

V tejto chvili sme poskytli cez tesla.show_car_name objekt tesla, ktora ma definovane atributy color a car_name.
V tomto sa najme lisi metoda od funkcie, metoda si pameta objekt, s ktorym pracuje.

In [12]:
class Car():
    def show_car_name(self):
        print ("Car {} has color: {}".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
In [13]:
tesla1 = Car()
tesla1.color = "blue"
tesla1.car_name = "Tesla model blue"
tesla1.change_km(19000)
Car Tesla model blue has 19000 km.

__init__

Nastavenie argumentov, atributov triedy je mozne aj priamo v definicii triedy. Tym vyriesime problem , ze musime priradovat vzdy ku kazdemu objektu nazov a farbu.
Ideme prepisat triedu tak, aby sa zakladne atributy nastavili pri inicializacii triedy pomocou metody init.
Metoda init sa zavola automaticky pri vytvarani noveho objektu.

In [14]:
class Car():
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name

    def show_car_name(self):
        print ("Car {} has color: {}".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
In [15]:
my_car = Car(color="white", car_name="Svetine auto")
my_car.show_car_name()
my_car.change_km(1000)
Car Svetine auto has color: white
Car Svetine auto has 1000 km.
In [16]:
class Car():
    #staticka premenna
    wheels = 4
    
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name

    def show_car_name(self):
        print ("Car {} has color: {}".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
In [17]:
Car.wheels
Out[17]:
4
In [18]:
class Car():
    #staticka premenna
    wheels = 4
    
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name
    
    @staticmethod
    def make_car_sound():
        print ('VRM!')

    def show_car_name(self):
        print ("Car {} has color: {}".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
In [19]:
Car.make_car_sound()
VRM!
In [20]:
Car.show_car_name()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-9d06e324a22e> in <module>()
----> 1 Car.show_car_name()

TypeError: show_car_name() missing 1 required positional argument: 'self'

Dedicnost

In [21]:
class SportCar():
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name

    def show_car_name(self):
        print ("Car {} has color: {} and use nafta".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
    
    def turn_on(self):
        print ("Turn on sport mode")
        

class ElectricCar():
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name

    def show_car_name(self):
        print ("Car {} has color: {} and do not use nafta".format(self.car_name, self.color))
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))
    
    def start(self):
        print ("Car starts.")
In [22]:
class Car():
    def __init__(self, color, car_name):
        self.color = color
        self.car_name = car_name
    
    def change_km(self, km):
        print ("Car {} has {} km.".format(self.car_name, km))

class SportCar(Car):
    def show_car_name(self):
        print ("Car {} has color: {} and use nafta".format(self.car_name, self.color))
        
    def turn_on(self):
        print ("Turn on sport mode")

class ElectricCar(Car):
    def show_car_name(self):
        print ("Car {} has color: {} and do not use nafta".format(self.car_name, self.color))
        
    def start(self):
        print ("Car starts.")
In [23]:
rapid = SportCar(color="red", car_name="Rapid Sport")
tesla = ElectricCar(color="black", car_name="My tesla")
rapid.change_km(100)
tesla.change_km(200)
rapid.show_car_name()
tesla.show_car_name()
rapid.turn_on()
tesla.start()
Car Rapid Sport has 100 km.
Car My tesla has 200 km.
Car Rapid Sport has color: red and use nafta
Car My tesla has color: black and do not use nafta
Turn on sport mode
Car starts.
In [24]:
tesla.turn_on()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-24-dc29c47a5338> in <module>()
----> 1 tesla.turn_on()

AttributeError: 'ElectricCar' object has no attribute 'turn_on'

Pouzitie super()

Obcas sa moze stat, ze chceme v metode ponechat povodnu funkcnost a pridat nieco navyse. To robime vdaka funkcii super(), pomocou ktorej volane metody z natriedy

In [25]:
class AnotherCar(Car):
    def __init__(self, color, car_name):
        car_name = car_name.upper()
        super().__init__(color, car_name)
    
    def change_km(self, km):
        print ("Car {} is not in km :( {}.".format(self.car_name, int(km/100)))
        super(AnotherCar, self).change_km(km)
    
In [26]:
boat = AnotherCar(color="green", car_name="My boat")
boat.change_km(299)
Car MY BOAT is not in km :( 2.
Car MY BOAT has 299 km.

Polymorfizmus

In [27]:
cars = [SportCar('orange', 'my car'), ElectricCar('pink', 'car2')]
In [28]:
for car in cars:
    car.show_car_name()
    car.change_km(100)
Car my car has color: orange and use nafta
Car my car has 100 km.
Car car2 has color: pink and do not use nafta
Car car2 has 100 km.
In [29]:
from abc import ABCMeta, abstractmethod
class Vehicle(object):
    __metaclass__ = ABCMeta

    base_sale_price = 0
    wheels = 0
    
    def __init__(self, vehicle_name):
        self.vehicle_name = vehicle_name
    
    @abstractmethod
    def vehicle_type(self):
        pass
In [30]:
class Car(Vehicle):
    base_sale_price = 8000
    wheels = 4

    def vehicle_type(self):
        return 'car'
In [31]:
class Aeroplane(Vehicle):
    base_sale_price = 10000
    wheels = 2

    def vehicle_type(self):
        return 'aeroplane'

Vyuzitie v datach

V datach sa to napriklad vyuzivaju triedy pre definovanie objektov, ktore reprezentuju objekty v databaze.


Na obrazku nizsie predstavuje:
Nazov triedy - nazov tabulky v db
Atributy triedy - stlpce tabulky a ich datove typy
Vyplnene instancie triedy budu uz konkretne riadky (data) v databaze
Metody modifikuju a pracuju s datami. Priklad prevod nadpisu do citatelnej podoby. Uprava meny na ceske koruny

Random

Ukazky prace s random

In [32]:
from random import randint, randrange
import random
print(randint(0,10))
print (randrange(1,10))
print (random.choice([1, 2, 9, 3]))
print (random.choice(["sveta", "riso"]))
8
4
9
riso

Sposoby vypisu

Existuju viacere

In [33]:
name = "Sveta"
print ("Moje meno je " + name)
print ("Moje meno je", name)
print ("Moje meno je {}".format(name))
print ("Moje meno je %s" %(name))
Moje meno je Sveta
Moje meno je Sveta
Moje meno je Sveta
Moje meno je Sveta

Pokemon hra

Nasa hra bude pozostavat z funkcionality:

  • Moznost vybrat si jedneho zo 4 zakladnych pokemonov
  • Zapasit s pokemonom voci superovi. Superom bude pocitac

Krok 1 - vydefinovanie objektov

Budeme pracovat so 4 pokemonmi.

Atributy, ktore su spolocne

In [34]:
from random import randint
from IPython.display import Image

pokemons = {"1" : "Pikacu", "2" : "Carmander", "3" : "Bulbasaur", "4" : "Sqirtl"}

class Pokemon():
    def __init__(self):
        self.name = ""
        self.health = 50
        self.color = ''
    
    def do_damage(self, enemy):
        damage = randint(0, 5)
        enemy.health = enemy.health - damage
        if damage == 0: 
            print ("%s evades %s's attack with %d." %(enemy.name, self.name, damage))
        else:
            print ("%s hurts %s with %d!" %(self.name, enemy.name, damage))
            self.tired()
            return enemy.health
    
    
    def status(self):
        print ("%s's health: %d" % (self.name, self.health))
        
class Enemy(Pokemon):
    def __init__(self, player):
        Pokemon.__init__(self)
        self.health = randint(1, player.health)
        
    
    
        
class Player(Pokemon):
    def __init__(self):
        Pokemon.__init__(self)
        self.health = randint(1,50)
    
    def tired(self):
        print ("%s feels tired." % self.name)
        self.health = max(1, self.health - 5)
    
    def attack(self):
        if self.do_damage(self.enemy):
            print ("%s executes %s!" % (self.name, self.enemy.name))
In [38]:
your_name = input("What is your name? ")
my_pokemon = random.choice(list(pokemons.items()))[1]

def choose():
    enemy_pokemon = random.choice(list(pokemons.items()))[1]
    return enemy_pokemon

enemy_pokemon = choose()

while True:
    if enemy_pokemon == my_pokemon:
        enemy_pokemon = choose()
        continue
    else:
        break
        
print ("************************************************")
p = Player()
e = Enemy(p)
p.name = my_pokemon
e.name = enemy_pokemon

def set_color(pokemon):
    if pokemon == "Pikacu":
        p.color = Image(url='http://localhost:8888/files/img/yellow.gif')
    elif pokemon == "Carmander":
        p.color = Image(url='http://localhost:8888/files/img/red.gif')
    elif pokemon == "Bulbasaur":
        p.color = Image(url='http://localhost:8888/files/img/green.gif')
    else:
        p.color = Image(url='http://localhost:8888/files/img/blue.gif')

set_color(p.name)

def show_winner(name):
    return name 

print ("%s your pokemon is: %s" % (your_name, my_pokemon))
print ("%s your pokemon is: %s" % ("Computer", enemy_pokemon))
print ("************************************************")
print ("%s enters a battle field. Fight with %s can start! " % (p.name, e.name))

round_number = 0
winner = Image(url='')

while True:
    if round_number == 6:
        print ("%s win the game in the %d round" % (e.name, round_number))
        winner = show_winner(e.color)
        break
    else:
        if e.health >= 0:
            p.status()
            e.status()
            p.do_damage(e)
            round_number +=1
            continue
        else:
            print ("%s win the game in the %d round" % (p.name, round_number))
            winner = show_winner(p.color)
            break

winner
What is your name? Sveta
************************************************
Sveta your pokemon is: Pikacu
Computer your pokemon is: Carmander
************************************************
Pikacu enters a battle field. Fight with Carmander can start! 
Pikacu's health: 39
Carmander's health: 6
Pikacu hurts Carmander with 3!
Pikacu feels tired.
Pikacu's health: 34
Carmander's health: 3
Pikacu hurts Carmander with 4!
Pikacu feels tired.
Pikacu win the game in the 2 round
Out[38]: