Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Hodně otázek po kódu v Pythoně

V předchozím kvízu, Online test znalostí Python 2.7, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Alexandr Saveljev:19.8.2023 14:51

Omlouvám se za velký kód. Potřebuje ho pro několik otázek. Kód je:

def prevedCisloNaZnak(cislo):
    if (cislo >= 0 and cislo <= 9):
        return chr(cislo + ord('0'))
    else:
        return chr(cislo - 10 + ord('A'))


# Funkce převádí číslo z desítkové soustavy na zvolenou jinou soustavu
def fromDeci(vysledek, baze, zadaneCislo):
    # Cyklus opakovaně dělí zadané desítkové číslo zadanou bází (typem soustavy, do níž chce uživatel zadané číslo převést)
    while (zadaneCislo > 0):
        vysledek += prevedCisloNaZnak(zadaneCislo % baze)
        zadaneCislo = int(zadaneCislo / baze)
    # hodnotu výsledku je nutné převrátit
    vysledek = vysledek[::-1]
    return vysledek


# Funkce nacte od uživatele číslo, které chce převést.
# Načtené číslo musí být kladný integer.
def nactiCislo(text_zadani, text_chyba):
    spatne = True
    while spatne:
        try:
            nacteneCislo = int(input(text_zadani))
            if nacteneCislo < 0:
                print("Zadané číslo musí být nezáporné!\n")
                continue
            spatne = False
        except ValueError:
            print(text_chyba)
        else:
            return nacteneCislo


        # Funkce nacte od uivatele číslo soustavy, na kterou che převést.
# Načtené číslo musí být kladný integer.
def nactiBazi(text_zadani, text_chyba):
    spatne = True
    while spatne:
        try:
            nactenaBaze = int(input(text_zadani))
            if nactenaBaze < 0:
                print("Zadané číslo musí být nezáporné!\n")
                continue
            if nactenaBaze < 2 or nactenaBaze > 16:
                print("Zadané číslo musí v rozmezí 2-16!\n")
                continue
            spatne = False
        except ValueError:
            print(text_chyba)
        else:
            return nactenaBaze

        # Hlavní program
zadaneCislo = nactiCislo("Číslo v desítkové soustavě: ", "Neplatné číslo!\n")
baze = nactiBazi("Číselná soustava (2-16): ", "Neplatné zadání!\n")
vysledek = ""
print("Číslo ve zvolené soustavě:", fromDeci(vysledek, baze, zadaneCislo))

Otázka první. V této části kódu:

if (cislo >= 0 and cislo <= 9):

poprve jsem napsal or namísto and a měl chybní odpověď.
Pomozte prosím pochopit jaký je rozdil tady mezi or a and v kódu.

Zkusil jsem: Zkusil jsem napsat různé, ale nachapu.

Chci docílit: Porozumění.

 
Odpovědět
19.8.2023 14:51
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:19.8.2023 15:30

OR (logický součet) - je operátor, který pracuje nad dvěma výrazy a vyhodnocuje celý výraz jako True, je-li alespoň jeden z výrazů True.

AND (logický součin) - je operátor, který pracuje nad dvěma výrazy a vyhodnocuje celý výraz jako True, jsou-li oba výrazy True.

Ve funkci:

def prevedCisloNaZnak(cislo):
    if (cislo >= 0 and cislo <= 9):
        return chr(cislo + ord('0'))
    else:
        return chr(cislo - 10 + ord('A'))

Chceme řešit podmínku, kde cislo bude jednou z číslicí 0,1,2,3,4,5,6­,7,8,9. Zajímá nás tedy rozsah 0 až 9. Jeden interval je 0 včetně, druhý je 9 včetně. Řešíme vnitřek. Můžeme si říci. cislo musí být větší nebo rovno 0 a zároveň ale cislo musí být menší nebo rovno 9. Když by sis nakreslil čáru jako osu, na ni označil bod 0 a bod 9 a vykreslil obě podmínky. Tak jedna začína od nuly doprava a druhá od 9 doleva. Tam kde jsou oboje platná, je výsledek pro AND. Pokud bys použil OR, je výsledek to kde alespoň jedna podmínka je platná. To by bylo vždy a funkce by nefungovala správně.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
19.8.2023 15:30
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:19.8.2023 15:36

Ještě jeden dodatek k logickým operátorům. V Pythonu funguje tzv. zkrácené vyhodnocování. Pokud pro AND se první výraz vyhodnotí jako False, pak se již druhý výraz nevyhodnocuje a výsledek je False. Pokud pro OR se první výraz vyhodnotí jako True, pak se druhý výraz již nevyhodnocuje a výsledek je True.

Nahoru Odpovědět
19.8.2023 15:36
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:19.8.2023 15:54

No a nakonec místo dvou funkcí nactiCislo() a nactiBazi() by mohla být jen funkce jedna. Pro omezení báze v rozsahu 2-16 použiješ nekonečný cyklus spolu s příkazem break při pravdivé podmínce na rozsah.

Nahoru Odpovědět
19.8.2023 15:54
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:20.8.2023 12:28

nactiCislo() a nactiBazi() by mohla být jen funkce jedna - nevím. Potřebujeme return, ale jak je možné vrátit 2 proměnné najednou?

 
Nahoru Odpovědět
20.8.2023 12:28
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:20.8.2023 13:11

Však funkce bude vracet vždy jen jednu hodnotu. Jen tu jednu funkci použiješ jak pro čtení čísla tak pro čtení báze.

zadaneCislo = nactiCislo("Číslo v desítkové soustavě: ", "Chyba!\n")
while True:
    baze = nactiCislo("Číselná soustava (2-16): ", "Chyba!\n")
    if baze >= 2 and baze <= 16:
        break
Nahoru Odpovědět
20.8.2023 13:11
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:20.8.2023 14:05

Ten kód ještě měl kód pro zaporné číslo.
Ale jo, BRAVO!
Velmí dobrá idea!
Děkuji!

 
Nahoru Odpovědět
20.8.2023 14:05
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:20.8.2023 15:54

Není zač. Ošetření záporného čísla je již ve funkci nactiCislo(). Pro bázi pak implementujeme pouze to co funkce neobsahuje, tedy povolený rozsah.

Nahoru Odpovědět
20.8.2023 15:54
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:21.8.2023 9:31

Druhá otázka.
V def nactiBazi používáme po if operator continue.
Ale v kódu def prevedCisloNaZnak(cislo): to neděláme.
Proč?

 
Nahoru Odpovědět
21.8.2023 9:31
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:21.8.2023 10:06

Continue není operátor ale řídící příkaz. Nikterak nesouvisí s řídícím příkazem if ale souvisí s cykly. Pokud se řídící příkaz continue nachází uvnitř cyklu, přeskočí se zbytek příkazů mezi ním a koncem cyklu ve kterém se nachází a provede se další iterace cyklu. Funkce prevedCisloNaZnak() neobsahuje žádný cyklus, tudíž použití řídícího příkazu continue uvnitř funkce by bylo nesmyslné a chybné. Naproti tomu funkce nactiBazi() obsahuje cyklus while a tak příkaz continue provede novou iteraci cyklu, aby se provedlo nové načítání, když je rozsah neplatný.

Nahoru Odpovědět
21.8.2023 10:06
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:21.8.2023 11:04

Teď jasně!
Další otázka.
Podívej se prosím na kód:

def nactiCislo(text_zadani, text_chyba):
    spatne = True
    while spatne:
        try:
            nacteneCislo = int(input(text_zadani))
            if nacteneCislo < 0:
                print("Zadané číslo musí být nezáporné!\n")
                continue
            spatne = False
        except ValueError:
            print(text_chyba)
        else:
            return nacteneCislo

Mohu Tě požádat, aby popsal kód slovy? Úplně nerozumím logice kódu.
Např.:

def nactiCislo(text_zadani, text_chyba):
    Předpokládejme „chybné/spatne“ = True
    "while/kdežto" je to tak, to:
        snažíme se:
            nacteneCislo = int(input(text_zadani))
            jestliže nacteneCislo < 0:
                print("Zadané číslo musí být nezáporné!\n")
                continue
            teď se snažíme že "spatne" = False
        s výjimkou ValueError:
            print(text_chyba)
        a jestli "spatne" = False, tehdy:
            return nacteneCislo

Uvědomuji si, že to vypadá trochu divně, ale pomohlo by mi to správně porozumět kódu.

 
Nahoru Odpovědět
21.8.2023 11:04
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:21.8.2023 11:49

Zde je kód s popisem činnosti funkce:

def nactiCislo(text_zadani, text_chyba):
    # Předpokládáme, že na začátku máme situaci, kdy je zadané číslo špatné (spatne = True)
    spatne = True

    # Toto je cyklus, který bude probíhat, dokud je spatne True
    while spatne:
        try:
            # Snažíme se načíst číslo ze vstupu
            nacteneCislo = int(input(text_zadani))

            # Pokud je načtené číslo menší než nula
            if nacteneCislo < 0:
                print("Zadané číslo musí být nezáporné!\n")
                continue  # Pokračujeme v cyklu, protože chceme znovu načíst číslo

            # Pokud jsme dosud neměli žádné problémy s načítáním, změníme hodnotu spatne na False
            # Tímto způsobem říkáme, že jsme úspěšně načetli platné číslo
            spatne = False

        # Pokud se nepodaří převést vstup na číslo (zachyceno ValueError)
        except ValueError:
            print(text_chyba)

    # Pokud jsme úspěšně načetli platné číslo a změnili spatne na False, provedeme návrat tohoto čísla
    return nacteneCislo

jinými slovy:

Načti text a převeď jej na číslo. Pokud při převodu na číslo dojde k chybě, vypiš chybovou hlášku. Pokud je převod úspěšný, ulož je do proměnné nacteneCislo. Je-li číslo záporné, vypiš chybovou hlášku o zopakuj celý proces. V opačném případě vrať číslo z funkce.

Nahoru Odpovědět
21.8.2023 11:49
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:21.8.2023 12:13

Funkci lze zjednodušit odstraněním proměnné spatne a použít break pro vyskočení z cyklu.

def nactiCislo(text_zadani, text_chyba):
    while True:
        try:
            nacteneCislo = int(input(text_zadani))
            if nacteneCislo < 0:
                print(text_chyba)
            else:
                break
        except ValueError:
            print(text_chyba)
    return nacteneCislo

def main():
    zadaneCislo = nactiCislo("Číslo v desítkové soustavě: ", "Chyba!\n")
    print(f"Zadané číslo: {zadaneCislo}")

if __name__ == "__main__":
 main()
Nahoru Odpovědět
21.8.2023 12:13
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:21.8.2023 18:39

Tj. spatne = False je možné vidět jako řídící příkaz STOP pro tento cyklus try: ?
Tj. spatne = False hraje stejnou roli jako i řídící příkaz continue v cyklu if nacteneCislo < 0:?

 
Nahoru Odpovědět
21.8.2023 18:39
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:21.8.2023 19:29

Ne, spatne je řídící proměnnou cyklu while. Ten na začátku každé interakce testuje proměnnou zda-li je True. Jinými slovy testuje zda došlo k chybě. Pro první iteraci je třeba, aby byla nastavena na True, neboť se neví, zda pozdější načtení proběhlo v pořádku. Continue neukončuje cyklus, naopak provede další iteraci. A ano, False ve spatne se provede totéž co continue, obojí totiž představuje, že došlo k chybě a vynuti opakování načítání. Try příkaz vymezuje kód který je testován ba chybu. Hledání typu výjimky je pak v sekci except.

Nahoru Odpovědět
21.8.2023 19:29
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:22.8.2023 10:50

Velmi dobře!
Jdeme dál.
Je mi líto, nerozimím této části kódu:

if __name__ == "__main__":
 main()

Co to znamená?
Poraď prosím.

 
Nahoru Odpovědět
22.8.2023 10:50
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:22.8.2023 11:00

if __name__ == "__main__": je konstrukce v Pythonu, která se používá k určení, zda je aktuální skript spuštěn jako hlavní program nebo je importován jako modul do jiného skriptu. Pokud ano, spustí se funkce main().

Nahoru Odpovědět
22.8.2023 11:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Alexandr Saveljev
DarkCoder:22.8.2023 11:18

Pokud neplánuješ importovat modul do jiného, není třeba vytvářet funkci main() a přidávat výše uvedenou konstrukci

def nactiCislo(text_zadani, text_chyba):
    while True:
        try:
            nacteneCislo = int(input(text_zadani))
            if nacteneCislo < 0:
                print(text_chyba)
            else:
                break
        except ValueError:
            print(text_chyba)
    return nacteneCislo

# Hlavní program
zadaneCislo = nactiCislo("Číslo v desítkové soustavě: ", "Chyba!\n")
print(f"Zadané číslo: {zadaneCislo}")
Nahoru Odpovědět
22.8.2023 11:18
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Alexandr Saveljev:22.8.2023 11:38

je konstrukce v Pythonu, která se používá k určení, zda je aktuální skript spuštěn jako hlavní program - och, ne, Já jsem jen začal studovat a tento skript prostě vezmu v úvahu.
Děkuji!

 
Nahoru Odpovědět
22.8.2023 11:38
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 19 zpráv z 19.