Wyjątek ValueError a pętla for

Wyjątek ValueError a pętla for
Sevy
  • Rejestracja:prawie 6 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:Katowice
  • Postów:20
0

Cześć. Na początku chciałbym się przywitać bo to mój pierwszy post. :)

Napisałem krótki quiz z tabliczki mnożenia. Pięć pytań, licznik punktów, itd.
W odpowiedzi należy podać liczbę, ale liczę się z tym, że ktoś może wpisać coś innego, więc nie chcę, żeby wyskakiwał mi błąd, dlatego chciałem dodać wyjątek "ValueError".
Próbowałem w niego wsadzić całą pętlę, ale po wpisaniu pięciokrotnie błędu pętla się kończy i tyle. Chciałbym, żeby zadawało pytanie dopóki użytkownik nie wpisze liczby.

Kopiuj
import random

points = 0

for answers in range(0, 5):
    numberA = random.randint(1, 10)
    numberB = random.randint(1, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    answer = int(input('Odpowiedź: '))
    if answer == result:
        points+=1
        print('Dobrze! Zdobyłeś punkt!')
    else:
        print('Błąd!')
print('Twój wynik to:', str(points) +'/5 punktów')

@Edit:

Chyba dałem radę w inny sposób, ale jakoś nie jestem do tego przekonany.

Kopiuj
import random

points = 0
a = 1

while a <= 5:
    numberA = random.randint(1, 10)
    numberB = random.randint(1, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    try:
        answer = int(input('Odpowiedź: '))
        if answer == result:
            points+=1
            a+=1
            print('Dobrze! Zdobyłeś punkt!')
        else:
            a+=1
            print('Błąd!')
    except ValueError:
        print('Nieprawidłowa wartość!')
        continue
print('Twój wynik to:', str(points) +'/5 punktów')
edytowany 1x, ostatnio: Sevy
AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:7 dni
  • Postów:973
1

Ładniej i czytelniej by było jakbyś stworzył funkcję do pobierania odpowiedzi użytkownika i to w niej zawarł właśnie wyjątek


Zdalna praca dla Senior Python Developerów --> PW
SI
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 9 godzin
2

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

Kopiuj
import random

points = 0


for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')
edytowany 2x, ostatnio: sig
NieUmiemProgramować
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 4 lata
  • Postów:17
0
sig napisał(a):

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

Kopiuj
import random

points = 0


for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')

@sig
jestem 'noobem' w programowanie dlatego pytam.
Czy jeśli zmieniłeś pętle while na for to zwiększanie zmiennej a nie traci sensu? pętla for chyba i tak wykona się 5 razy?

Pytam bo nie wiem, czy to przeoczenie, czy ja czegoś nie rozumiem.

Guaz
Słusznie zauważyłeś, czasem przerabiając cudze kody pomija się takie fragmenty, po prostu zmieniasz fragmenty interesujące cię w perspektywie problemu, nie żeby go całego przerabiać i usuwać zbędne rzeczy. To z reguły pozostaje pytającemu zauważyć, jak tobie słusznie się udało :)
Sevy
  • Rejestracja:prawie 6 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:Katowice
  • Postów:20
0

co tu robi while 1? jak on działa?

sig napisał(a):

Ja bym w przypadku podania nie inta zapytał jeszcze raz, i o mnożenie przez jeden nie pytał. Dodatkowo for zamiast twojego while

Kopiuj
import random

points = 0


for a in range(5):
    numberA = random.randint(2, 10)
    numberB = random.randint(2, 10)
    result = numberA * numberB
    print('Ile to jest', numberA,'razy', str(numberB) + '?')
    while 1:
        try:
            answer = int(input('Odpowiedź: '))
            if answer == result:
                points+=1
                a+=1
                print('Dobrze! Zdobyłeś punkt!')

            else:
                a+=1
                print('Błąd!')
            break
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')

print('Twój wynik to:', str(points) +'/5 punktów')
Guaz
while 1: to tyle samo co while True:, bardzo popularny zapis dla piszących w C (? Tak coś mi świta). Jest to nieskończona pętla, kończy się tylko i wyłącznie jak dojdzie do kodu break.
SI
Znam ją faktycznie z c++, ale jest chyba popularna w wszystkich językach.
Guaz
PS: Jeszcze skończy się ta pętla w wyniku błędu którego nie przechwycisz poprzez try/except, oraz kilka bardziej zaawansowanych rzeczy z wątkami. No względnie tak, chociaż o ile pamięć mnie nie myli w Javie nie ma bata, while (1): nie zadziała :D. Ogólnie można tak pisać, nie jest to żaden błąd, ot początkowy zamysł while (warunek) jest najczytelniejsze, natomiast True/False z reguły zwracają wszelkie warunki. Ale w pythonie to i tak można robić cuda, dawać while (lista) a wewnątrz pętli usuwać elementy ;d. Jak struktura będzie pusta, to zostanie zrzutuowana na False.
SI
Kolejna pozostałość po jego kodzie, zwykle w takich przypadkach stosuję samo except bez "kategorii".
SI
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 9 godzin
0

Skoro już poprawiamy, to może by tak w przypadku błędu podać prawidłową odpowiedź? Użytkownik szybciej się nauczy. A także pytać aż poda 5 poprawnych odpowiedzi, i podać mu ilu prób potrzebował żeby to osiągnąć.

AN
  • Rejestracja:prawie 11 lat
  • Ostatnio:7 dni
  • Postów:973
2

Kilka uwag co do kodu.

Po 1. staramy się zawsze żeby wyjątki obejmowały tylko obszar kodu, w którym ten wyjątek faktycznie może wystąpić.

Więc kod

Kopiuj
      try:
           answer = int(input('Odpowiedź: '))
           if answer == result:
               points+=1
               a+=1
               print('Dobrze! Zdobyłeś punkt!')

           else:
               a+=1
               print('Błąd!')
           break
       except ValueError:
           print('Nieprawidłowa wartość! wpisz jeszcze raz')

zamieniamy na np.

Kopiuj
        try:
            answer = int(input('Odpowiedź: '))
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')
            continue
            
        if answer == result:
            points+=1
            a+=1
            print('Dobrze! Zdobyłeś punkt!')
        else:
            a+=1
            print('Błąd!')
        break

Co też można pozmieniać. Po 1. zmienna a już nie będzie potrzebna. Po 2. można skorzystać tu z funkcji. Zmienić nazwy zmiennych. numberA zmienić albo na numer_a albo na samo a. Jednoliterowe zmienne generalnie są potępiane ale w tym przypadku mogę być zastosowane bo są jednoznaczne.
Możemy skorzystać z formatowania tekstu zamiast kleić string jak w czasach prehistorycznych czyli:

print('Ile to jest', a ,'razy', str(b) + '?') zmieniamy na np. print(f'Ile to jest {a} razy {b}?') lub korzystamy z format jeśli nie nasza wersja Pythona nie wspiera f-stringów.

Więc poprawiony kod mógłby wyglądać tak:

Kopiuj
import random

points = 0

def get_answer():
    while True:
        try:
            return int(input('Odpowiedź: '))
        except ValueError:
            print('Nieprawidłowa wartość! wpisz jeszcze raz')


for _ in range(5):
    a = random.randint(2, 10)
    b = random.randint(2, 10)
    result = a * b
    
    print(f'Ile to jest {a} razy {b}?')
    answer = get_answer()
    
    if answer == result:
        points += 1
        print('Dobrze! Zdobyłeś punkt!')
    else:
        print('Błąd!')


print(f'Twój wynik to: {points}/5 punktów')

Dodatkowo można by jeszcze pokusić się o dodatkową zmienną przechowującą ile prób powinien mieć użytkownik. Chodzi tu o liczbę 5 bo jest ona dosyć magiczna (magic number). Wtedy w jednym miejscu zmieniamy ile użytkownik ma prób. Aktualnie żeby z 5 zrobić 6 musisz to zmienić w dwóch miejscach (w pętli oraz przy wyświetleniu wyników)


Zdalna praca dla Senior Python Developerów --> PW
edytowany 2x, ostatnio: anonimowy

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.