Knyga/Loginiai reiškiniai: Skirtumas tarp puslapio versijų

Iš Pitonas.
Nėra keitimo santraukos
Nėra keitimo santraukos
 
(nerodoma 3 tarpinės versijos, sukurtos 2 naudotojų)
1 eilutė: 1 eilutė:
{{navigation |previous=Pasirinkimai |next=Ciklai For}}
{{navigation |previous=Pasirinkimai |next=Ciklai For}}
=== Ką išmoksi šiame skyriuje? ===
* Kas yra loginė reikšmė <code>True</code> ir <code>False</code>
* Kaip veikia loginiai operatoriai: <code>and</code>, <code>or</code>, <code>not</code>
* Kada naudojamas „tingus“ įvertinimas (short-circuit evaluation)
* Kaip grupuoti sąlygas su skliausteliais
* Kaip palyginti tekstus ar skaičius naudojant loginę logiką
* Kaip Python interpretuoja loginę reikšmę įvairiems objektams
* Kokios yra dažniausios loginės klaidos pradedantiesiems
* Kaip parašyti programas su keliomis susijusiomis loginėmis sąlygomis
[[Vaizdas:TrueFalse.png|center|frameless|953x953px]]  
[[Vaizdas:TrueFalse.png|center|frameless|953x953px]]  
   
   
109 eilutė: 121 eilutė:
Turėk omeny, jei pirmasis reiškinys yra teisingas Python’as nebetikrins antrojo, kadangi jis žino, jog visas reiškinys bus teisingas. Kaip jau minėjau anksčiau, naudojant operatorių <code>or</code>, jei bent vienas iš reiškinių yra teisingas, tuomet viso reiškinio galutinis rezultatas bus teisingas. Pirmoji dalis yra teisinga, todėl antroji dalis gali būti klaidinga arba teisinga, tačiau visa išraiška vis dar teisinga.
Turėk omeny, jei pirmasis reiškinys yra teisingas Python’as nebetikrins antrojo, kadangi jis žino, jog visas reiškinys bus teisingas. Kaip jau minėjau anksčiau, naudojant operatorių <code>or</code>, jei bent vienas iš reiškinių yra teisingas, tuomet viso reiškinio galutinis rezultatas bus teisingas. Pirmoji dalis yra teisinga, todėl antroji dalis gali būti klaidinga arba teisinga, tačiau visa išraiška vis dar teisinga.


Aštuntoje: <code>print(8, not (a == 7 and b == 6))</code> ir devintoje: <code>print(9, not a == 7 and b == 6)</code> eilutėse yra atvaizduojamas reiškinių grupavimo pavyzdys. Reiškinius Python’e galima sugrupuoti naudojant skliaustelius. Sugrupavę reiškinius, mes priverčiame Python’ą iš pradžių įvertinti reiškinius skliaustuose ir tik tada likusias reiškinio dalis. Atkreipk dėmesį, kad skliausteliai pakeitė reiškinį iš neteisingo į teisingą. Taip nutiko dėl to, kad operatorius <code>not</code> buvo pritaikytas reiškiniui skliausteliuose, vietoj to, kad būtų pritaikytas tik <code>a == 7</code> daliai.  
Aštuntoje: <code>print(8, not (a == 7 and b == 6))</code> ir devintoje: <code>print(9, not a == 7 and b == 6)</code> eilutėse yra atvaizduojamas reiškinių grupavimo pavyzdys. Reiškinius Python’e galima sugrupuoti naudojant skliaustelius. Sugrupavę reiškinius, mes priverčiame Python’ą iš pradžių įvertinti reiškinius skliaustuose ir tik tada likusias reiškinio dalis. Atkreipk dėmesį, kad skliausteliai pakeitė loginės išraiškos vertinimo tvarką, todėl pasikeitė rezultatas.. Taip nutiko dėl to, kad operatorius <code>not</code> buvo pritaikytas reiškiniui skliausteliuose, vietoj to, kad būtų pritaikytas tik <code>a == 7</code> daliai.  
Parodysiu pavyzdį, kaip rašant kodą galima pritaikyti loginius operatorius:
Parodysiu pavyzdį, kaip rašant kodą galima pritaikyti loginius operatorius:


249 eilutė: 261 eilutė:


=== Pratimai ===
=== Pratimai ===
1. Parašyk programą, kurioje vartotojas turi atspėti tavo vardą, tačiau jie turės tik 3 spėjimus tai padaryti iki kol programa bus uždaryta.
1. Durys atsirakina tik tada, kai:
 
* yra įvestas teisingas kodas '''ir'''
* durys '''nėra užblokuotos'''.
 
Parašyk programą, kuri paprašo vartotojo įvesti durų kodą ir paklausia, ar durys yra užblokuotos. Tada praneša, ar duris galima atidaryti.
{| class="mw-collapsible mw-collapsed wikitable"
{| class="mw-collapsible mw-collapsed wikitable"
! colspan=2 | Sprendimas &nbsp;
! colspan="2" | Sprendimas &nbsp;
|-
|-
|
|
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
print("Pabandyk atspėti mano vardą!")
teisingas_kodas = "1234"
kiekis = 1
VARDAS = "gilbertas"
spėjimas = input("Koks mano vardas? ")
while kiekis < 3 and spėjimas.lower() != VARDAS:    # .lower visas didžiąsias raides teksto eilutėje pakeičia į mažąsias, todėl net jei vartotojas įves Gilbertas, tai vis tiek bus teisingas atsakymas
    print("Tu neteisus!")
    spėjimas = input("Koks mano vardas? ")
    kiekis = kiekis + 1


if spėjimas.lower() != VARDAS:
ivestas_kodas = input("Įveskite durų kodą: ")
    print("Tu neteisus!") # ši žinutė nėra atspausdinama trečiąjį bandymą, todėl mes tai padarome dabar
uzblokuotos = input("Ar durys užblokuotos? (taip/ne): ") == "taip"
     print("Tu nebegali spėti.")
 
if ivestas_kodas == teisingas_kodas and not uzblokuotos:
     print("Durys atrakintos.")
else:
else:
     print("Taip! Mano vardas yra", VARDAS + "!")
     print("Durų atidaryti negalima.")
</syntaxhighlight>
</syntaxhighlight>
|-
|-
295 eilutė: 307 eilutė:




3. Parašyk programą, kuri paprašytų sukurti stiprų slaptažodį. Reikalavimai stipriam slaptažodžiui:
3. Asmuo gali gauti paskolą, jei:


* Jis turėtų būti sudarytas iš daugiau nei 6 simbolių
* jo amžius yra '''18 metų ar daugiau''', '''ir'''
* Jis turėtų turėti bent vieną skaitmenį
* jo mėnesinės pajamos yra '''daugiau nei 1000''', '''ir'''
* Jis turėtų turėti bent vieną specialų simbolį iš šio sąrašo: !#$?
* jis '''nėra skolingas''' kitur.


Parašyk programą, kuri paprašo įvesti:


Programa turėtų išvesti, ar slaptažodis pakankamai stiprus, ar ne.
# Amžių
# Pajamas
# Ar žmogus turi skolų?


Ir praneša, ar gali gauti paskolą.
{| class="mw-collapsible mw-collapsed wikitable"
{| class="mw-collapsible mw-collapsed wikitable"
! colspan=2 | Sprendimas &nbsp;
! colspan="2" | Sprendimas &nbsp;
|-
|-
|
|
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
def ar_turi_skaičių(slaptažodis):
amžius = int(input("Įveskite savo amžių: "))
    skaičiai = "0123456789"
pajamos = float(input("Įveskite savo mėnesines pajamas: "))
    rezultatas = False
turi_skolų = input("Ar turite skolų? (taip/ne): ") == "taip"
    for raidė in slaptažodis:
        if raidė in skaičiai:
            rezultatas = True
            break
    return rezultatas
   
def ar_turi_simbolį(slaptažodis):
    simboliai = "!#$?"
    rezultatas = False
    for raidė in slaptažodis:
        if raidė in simboliai:
            rezultatas = True
            break
    return rezultatas
 
def ar_slaptažodis_stiprus(slaptažodis):
    ar_užtenka_simbolių = len(slaptažodis) > 6
    ar_yra_skaitmuo = ar_turi_skaičių(slaptažodis)
    ar_yra_simbolis = ar_turi_simbolį(slaptažodis)
    return ar_užtenka_simbolių and ar_yra_skaitmuo and ar_yra_simbolis
   
 
įvestas_slaptažodis = input("Įvesk slaptažodį: ")
ar_stiprus = ar_slaptažodis_stiprus(įvestas_slaptažodis)


if ar_stiprus:
if amžius >= 18 and pajamos > 1000 and not turi_skolų:
     print ("Slaptažodis pakankamai stiprus")
     print("Paskola suteikiama.")
else:
else:
     print ("Slaptažodis nepakankamai stiprus")
     print("Paskola nesuteikiama.")
</syntaxhighlight>
</syntaxhighlight>
|-
|-

Dabartinė 15:34, 5 rugpjūčio 2025 versija


Ką išmoksi šiame skyriuje?

  • Kas yra loginė reikšmė True ir False
  • Kaip veikia loginiai operatoriai: and, or, not
  • Kada naudojamas „tingus“ įvertinimas (short-circuit evaluation)
  • Kaip grupuoti sąlygas su skliausteliais
  • Kaip palyginti tekstus ar skaičius naudojant loginę logiką
  • Kaip Python interpretuoja loginę reikšmę įvairiems objektams
  • Kokios yra dažniausios loginės klaidos pradedantiesiems
  • Kaip parašyti programas su keliomis susijusiomis loginėmis sąlygomis


Šiame skyriuje padėsiu tau išsiaiškinti, kas yra loginiai reiškiniai. Sugalvojau nedidelį programos pavyzdį, kurio tau įvedinėti nebūtina:

a = 6
b = 7
c = 42
print(1, a == 6)
print(2, a == 7)
print(3, a == 6 and b == 7)
print(4, a == 7 and b == 7)
print(5, not a == 7 and b == 7)
print(6, a == 7 or b == 7)
print(7, a == 7 or b == 6)
print(8, not (a == 7 and b == 6))
print(9, not a == 7 and b == 6)

Šios programos išvestis yra:

1 True
2 False
3 True
4 False
5 True
6 True
7 False
8 True
9 False

Galvoje, turbūt, jau sukasi mintis: kas čia ką tik įvyko? Paaiškinsiu, kaip veikia kiekviena eilutė, kad mintys susidėliotų į savas vietas. Mano programoje gausu print sakinių, iš kurių kiekvienas išspausdina skaičių ir loginę reikšmę. Skaičius man padeda suprasti, kurio print sakinio rezultatas tai yra. Atkreipk dėmesį, kad kiekvienoje išvesties eilutėje yra žodis False (Klaidinga) arba True (Teisinga), o Python'e kiekviena loginė reikšmė False gali būti užrašoma skaičiumi 0, o True 1.


Eilučių:

print(1, a == 6)
print(2, a == 7)

rezultatas atitinkamai yra True ir False, kadangi pirmasis reiškinys yra teisingas, o antrasis yra klaidingas. Trečioji eilutė: print(3, a == 6 and b == 7) - šiek tiek skiriasi nuo prieš tai buvusių - joje yra naudojamas operatorius and. Loginis operatorius and grąžina rezultatą True tik tada, kai reiškiniai iš abiejų and pusių yra teisingi, kitu atveju visas reiškinys bus klaidingas ir grąžins False. Ketvirtoje eilutėje: print(4, a == 7 and b == 7) tik vienas iš reiškinių yra teisingas, dėl to eilutės rezultatas yra False. Operatoriaus and galimi rezultatai gali būti apibrėžti tokia lentele:

Reiškinys Rezultatas
True and True True
True and False False
False and True False
False and False False

Atkreipk dėmesį, jei pirmas reiškinys yra klaidingas, tai Python’as nebetikrins antrojo, kadangi jis žino, jog visas reiškinys yra klaidingas. Parašyk šias eilutes ir paleisk programą: False and print("Labas") ir palygink rezultatą su šios eilutės True and print("Labas") rezultatu. Techniškai tai yra vadinama sutrumpintos grandies įvertinimas (short-circuit evaluation). Penktoje eilutėje, print(5, not a == 7 and b == 7), yra naudojamas not operatorius. not suteikia priešingą reikšmę reiškiniui (reiškinys taip pat galėtų būti užrašomas taip: print(5, a != 7 and b == 7)). Štai lentelė apibrėžianti operatoriaus not rezultatus:

Reiškinys Rezultatas
not True False
not False True

Dvi toliau pateiktos eilutės: print(6, a == 7 or b == 7) ir print(7, a == 7 or b == 6) naudoja operatorių or. Pastarasis operatorius grąžina True jei pirmasis reiškinys yra teisingas arba, jei antrasis reiškinys yra teisingas, arba, jei abu reiškiniai yra teisingi. Jei nei vienas iš reiškinių nėra teisingas, tuomet yra grąžinamas False. Štai lentelė apibrėžianti operatoriaus or rezultatus:

Reiškinys Rezultatas
True or True True
True or False True
False or True True
False or False False

Turėk omeny, jei pirmasis reiškinys yra teisingas Python’as nebetikrins antrojo, kadangi jis žino, jog visas reiškinys bus teisingas. Kaip jau minėjau anksčiau, naudojant operatorių or, jei bent vienas iš reiškinių yra teisingas, tuomet viso reiškinio galutinis rezultatas bus teisingas. Pirmoji dalis yra teisinga, todėl antroji dalis gali būti klaidinga arba teisinga, tačiau visa išraiška vis dar teisinga.

Aštuntoje: print(8, not (a == 7 and b == 6)) ir devintoje: print(9, not a == 7 and b == 6) eilutėse yra atvaizduojamas reiškinių grupavimo pavyzdys. Reiškinius Python’e galima sugrupuoti naudojant skliaustelius. Sugrupavę reiškinius, mes priverčiame Python’ą iš pradžių įvertinti reiškinius skliaustuose ir tik tada likusias reiškinio dalis. Atkreipk dėmesį, kad skliausteliai pakeitė loginės išraiškos vertinimo tvarką, todėl pasikeitė rezultatas.. Taip nutiko dėl to, kad operatorius not buvo pritaikytas reiškiniui skliausteliuose, vietoj to, kad būtų pritaikytas tik a == 7 daliai. Parodysiu pavyzdį, kaip rašant kodą galima pritaikyti loginius operatorius:

amzius = int(input("Įveskite savo amžių: "))
turi_bilieta = input("Ar turite bilietą? (taip/ne): ") == "taip"

if amzius >= 18 and turi_bilieta:
    print("Galite įeiti į renginį.")
else:
    print("Negalite įeiti į renginį.")


Pastaba apie loginius operatorius

Dažna pradedančiųjų programuotojų klaida yra neteisingas supratimas, kaip veikia loginiai operatoriai ir kaip juos „skaito“ Python'o interpretatorius. Pavyzdžiui: vos tik sužinojus apie operatorius and ir or, galima pagalvoti, kad išraiška x == ('a' or 'b') patikrins, ar kintamasis x yra lygus a arba kintamasis x lygus b, tačiau taip nėra. Norint suprasti, apie ką kalbu, pradėk interaktyvią sesiją su interpretatoriumi ir įvesk šias išraiškas:

>>> 'a' == ('a' or 'b')
>>> 'b' == ('a' or 'b')
>>> 'a' == ('a' and 'b')
>>> 'b' == ('a' and 'b')

Štai yra rezultatai, kurie nėra intuityvūs:

>>> 'a' == ('a' or 'b')
True
>>> 'b' == ('a' or 'b')
False
>>> 'a' == ('a' and 'b')
False 
>>> 'b' == ('a' and 'b')
True

Šiuo momentu gali pasirodyti, jog operatoriai and ir or veikia klaidingai. Neatrodo logiška, jog pirmuose reiškiniuose 'a' yra lygu 'a' arba 'b', tačiau 'b' nėra lygu 'a' arba 'b'. Taip pat yra ir su paskutiniu reiškiniu - jis neatrodo teisingas, nes 'b' yra lygus 'a' ir 'b'. Išsiaiškinus, kaip veikia Python’o interpretatorius pasidaro aišku, kodėl gavome būtent tokius rezultatus.

Kai Python’o interpretatorius „pamato“ reiškinį, kuriame yra naudojamas or, jis paima pirmąjį teiginį ir patikrina ar jo rezultatas yra True. Jei pirmasis teiginys yra True, tuomet Python’as grąžina to teiginio rezultatą, netikrindamas antrojo. Kaip jau minėjau anksčiau, naudojant operatorių or užtenka patikrinti ar pirmasis teiginys yra teisingas, nes tada mes jau žinome, kad visas reiškinys yra teisingas ir programai nebereikia papildomai tikrinti antrojo. Iš kitos pusės, jei pirmasis teiginys grąžina False, tada Python’as turi patikrinti ir antrojo teiginio rezultatą bei grąžinti jo reikšmę. Antrasis teiginys nusako visos išraiškos rezultatą, kadangi pirmoji pusė buvo klaidinga. Šis interpretatoriaus „tingus“ įvertinimas vadinamas "short circuiting" ir yra įprastas būdas įvertinti logines išraiškas daugelyje programavimo kalbų.

Panašiai veikia ir operatorius and: Python’as naudoja, "short circuit" techniką, kad pagreitintų išraiškos įvertinimą. Jei pirmasis teiginys yra klaidingas, tada visas reiškinys yra klaidingas. Kitu atveju, jei pirmasis teiginys yra teisingas, tada Python’as patikrina antrąjį ir grąžina galutinę reikšmę.

Reiktų atkreiptį dėmesį į vieną niuansą: ne tik loginių išraiškų rezultatai gali būti apibrėžiami True arba False reikšmėmis. Norėdami patikrinti bet kurio objekto x loginę reikšmę, galite naudoti funkciją bool(x). Žemiau yra pateikiama lentelė, kurioje yra pavyzdžiai, kokiems objektams Python’as priskiria True arba False:

True False
True False
1 0
Skaičiai kitokie nei nulis Tekstinė eilutė 'None'
Ne tuščios tekstinės eilutės Tuščios tekstinės eilutės
Sąrašai (lists) turintys elementų Sąrašai (lists) neturintys elementų
Žodynai (dictionaries) turintys elementų Žodynai (dictionaries) neturintys elementų

Dabar galime suprasti gluminančius rezultatus, kuriuos gavome, kai anksčiau išbandėme logines išraiškas. Pažiūrėkime, ką Python'o interpretatorius „mato“, eidamas per šį kodą:

Pirmasis atvejis:

>>> 'a' == ('a' or 'b')  # Iš pradžių žiūrėk į reiškinį skliaustuose: "('a' or 'b')"
                           # 'a' yra netuščia teksto eilutė, todėl reiškinio rezultatas yra True
                           # Grąžink tą pirmą reikšmę: 'a'
>>> 'a' == 'a'           # teksto eilutė 'a' yra lygi teksto eilutei 'a', todėl reiškinio rezultatas yra True
True

Antrasis atvejis:

>>> 'b' == ('a' or 'b')  # Iš pradžių žiūrėk į reiškinį skliaustuose: "('a' or 'b')"
                           # 'a' yra netuščia teksto eilutė, todėl reiškinio rezultatas yra True
                           # Grąžink tą pirmą reikšmę: 'a'
>>> 'b' == 'a'           # teksto eilutė 'b' nėra lygi teksto eilutei 'a', todėl reiškinio rezultatas yra False
False 

Trečiasis atvejis:

>>> 'a' == ('a' and 'b') # Iš pradžių žiūrėk į reiškinį skliaustuose: "('a' and 'b')"
                           # 'a' yra netuščia teksto eilutė, todėl reiškinio rezultatas yra True, patikrinkime antrąją reikšmę
                           # 'b' yra netuščia teksto eilutė, todėl antrojo reiškinio rezultatas yra True
                           # Grąžink antrąją reikšmę kaip viso reiškinio rezultatą: 'b'
>>> 'a' == 'b'           # teksto eilutė 'a' nėra lygi teksto eilutei 'b', todėl reiškinio rezultatas yra False
False

Ketvirtasis atvejis:

>>> 'b' == ('a' and 'b') # Iš pradžių žiūrėk į reiškinį skliaustuose:
                           # 'a' yra netuščia teksto eilutė, todėl reiškinio rezultatas yra True, patikrinkime antrąją reikšmę
                           # 'b' yra netuščia teksto eilutė, todėl antrojo reiškinio rezultatas yra True
                           # Grąžink antrąją reikšmę kaip viso reiškinio rezultatą: 'b'
>>> 'b' == 'b'           # teksto eilutė 'b' yra lygi teksto eilutei 'b', todėl reiškinio rezultatas yra True
True 

Taigi, Python’as tikrai teisingai įvertino duotuosius reiškinius, kurių rezultatai iš pradžių neatrodė akivaizdūs. Kaip minėjau anksčiau, svarbu atpažinti, kokį rezultatą tavo loginė išraiška grąžins ir kodėl.

Grįžtant prie pradinių reiškinių, štai kaip juos turėtum aprašyti, kad jie grąžintų reikšmes, kurių tikiesi:

>>> 'a' == 'a' or 'a' == 'b' 
True
>>> 'b' == 'a' or 'b' == 'b' 
True
>>> 'a' == 'a' and 'a' == 'b' 
False
>>> 'b' == 'a' and 'b' == 'b' 
False

Įvertinus šiuos reiškinius yra gaunamos logines reikšmes True arba False, o ne teksto eilutės, kad galėtume gauti teisingus palyginimo rezultatus.

Pavyzdžiai

slaptazodis1.py

## Ši programa prašo vartotojo prisijungimo vardo ir slaptažodžio.
# Kai vartotojas juos įveda, programa įvertina ar jis gali prisijungti.

vardas = input("Koks tavo vardas? ")
slaptažodis = input("Koks tavo slaptažodis? ")
if vardas == "Benas" and slaptažodis == "Penktadienis":
    print("Sveikas, Benai!")
elif vardas == "Jonas" and slaptažodis == "Kietas":
    print("Sveikas, Jonai!")
else:
    print("Aš tavęs nepažįstu.")

Pavyzdiniai rezultatai:

Koks tavo vardas? Benas

Koks tavo slaptažodis? Penktadienis

Sveikas, Benai!


Koks tavo vardas? Andrius

Koks tavo slaptažodis? Pinigai

Aš tavęs nepažįstu.

Pratimai

1. Durys atsirakina tik tada, kai:

  • yra įvestas teisingas kodas ir
  • durys nėra užblokuotos.

Parašyk programą, kuri paprašo vartotojo įvesti durų kodą ir paklausia, ar durys yra užblokuotos. Tada praneša, ar duris galima atidaryti.

Sprendimas  
teisingas_kodas = "1234"

ivestas_kodas = input("Įveskite durų kodą: ")
uzblokuotos = input("Ar durys užblokuotos? (taip/ne): ") == "taip"

if ivestas_kodas == teisingas_kodas and not uzblokuotos:
    print("Durys atrakintos.")
else:
    print("Durų atidaryti negalima.")


2. Parašyk programą, kuri paprašytų įvesti du skaičius. Programa turėtų išvesti, ar abu skaičiai didesni už 10, ar abu skaičiai mažesni už 10, ar vienas didesnis, kitas mažesnis.

Sprendimas  
pirmas_skaičius = int(input("Įvesk pirmą skaičių: "))
antras_skaičius = int(input("Įvesk antrą skaičių: "))

if pirmas_skaičius > 10 and antras_skaičius > 10:
    print ("Abu skaičiai didesni nei 10")
elif pirmas_skaičius < 10 and antras_skaičius < 10:
    print ("Abu skaičiai mažesni nei 10")
else:
    print ("Vienas iš skaičių mažesnis nei 10")


3. Asmuo gali gauti paskolą, jei:

  • jo amžius yra 18 metų ar daugiau, ir
  • jo mėnesinės pajamos yra daugiau nei 1000, ir
  • jis nėra skolingas kitur.

Parašyk programą, kuri paprašo įvesti:

  1. Amžių
  2. Pajamas
  3. Ar žmogus turi skolų?

Ir praneša, ar gali gauti paskolą.

Sprendimas  
amžius = int(input("Įveskite savo amžių: "))
pajamos = float(input("Įveskite savo mėnesines pajamas: "))
turi_skolų = input("Ar turite skolų? (taip/ne): ") == "taip"

if amžius >= 18 and pajamos > 1000 and not turi_skolų:
    print("Paskola suteikiama.")
else:
    print("Paskola nesuteikiama.")