Wyrażenia logiczne w Pythonie
Do tej pory widzieliśmy zaledwie bardzo proste warunki sprawdzające wartość jednej zmiennej. Jak zachować się w sytuacji, gdy chcielibyśmy wykonać akcję, w której jednocześnie dwa warunki są spełnione? Na przykład:
- czy tweet jest promowany i pochodzi od osoby obserwowanej,
- czy tweet jest własny lub pochodzi od osoby obserwowanej.
Aby uzyskiwać odpowiedzi na takie pytania, potrzebujemy operatorów logicznych and
, or
i not
, które to wykonują operacje na wartościach logicznych (podobnie jak +
, -
i *
wykonują operacje na liczbach).
Operator and
Aby dobrze zrozumieć operatory logiczne, przytoczę historię małego Jasia. Chciał on pograć na komputerze, więc poszedł do mamy poprosić o pozwolenie. Ta jednak powiedziała: "Będziesz mógł pograć, gdy odrobisz lekcje i posprzątasz pokój".
Ten warunek w programowaniu mógłby być wyrażony następująco:
can_play_games = finished_homework and cleaned_room
Widzimy tam zmienne finished_homework
i cleaned_room
, reprezentujące kolejno ukończenie zadań domowych i posprzątanie pokoju (zakładamy, że są to wartości logiczne, czyli True
lub False
). Pomiędzy nimi widzimy natomiast operator and
1, który sprawia, że całe wyrażenie jest True
tylko wtedy, gdy obydwie jego strony są True
2.
a | b | a and b |
---|---|---|
True | True | True |
True | False | False |
False | True | False |
False | False | False |
print(True and True) # True
print(True and False) # False
print(False and True) # False
print(False and False) # False
# A czy Jasio może mieć szczeniaka?
have_time = True
is_responsible = False
can_have_puppy = is_responsible and have_time
print(can_have_puppy) # False
Za przykładowe częste wykorzystanie tego operatora uznaje się sprawdzenie, czy liczba znajduje się w jakimś zakresie: czy jest większa od minimum i mniejsza niż maksimum. Dla przykładu moglibyśmy sprawdzić, czy zmienna percent
ma poprawną wartość, czyli czy znajduje się między 0 a 100.
if percent >= 0 and percent <= 100:
print("Poprawna wartość")
Jeśli percent
będzie miał wartość z zakresu od 0 do 100, to zostanie wyświetlona "Poprawna wartość". W przeciwnym wypadku nic się nie stanie.
Operator or
Niestety Jasio nie odrobił lekcji, zatem nie mógł pograć na komputerze. Wtedy jednak zadzwonili do niego znajomi i zaprosili go do kina. Jasio poszedł do mamy i poprosił o pieniądze na wyjście. Ta powiedziała: "Dostaniesz pieniądze, jeśli posprzątasz garaż lub umyjesz samochód".
Ten warunek można przedstawić następująco:
can_go_to_cinema = cleaned_garage or washed_car
Operator or
3 reprezentuje alternatywę. Całe wyrażenie zwraca True
, gdy spełnione jest albo cleaned_garage
, albo washed_car
, albo oba te warunki jednocześnie.
a | b | a or b |
---|---|---|
True | True | True |
True | False | True |
False | True | True |
False | False | False |
print(True or True) # True
print(True or False) # True
print(False or True) # True
print(False or False) # False
# Czy Jasio dostanie czekoladę?
behaved_well = True
cleaned_room = False
can_eat_chocolate = behaved_well or cleaned_room
print(can_eat_chocolate) # True
Jasio tak się zapalił do pracy, że zarówno posprzątał garaż, jak i umył samochód. Zdziwiona mama powiedziała: "Chciałam, byś zrobił jedno albo drugie, a nie obydwa", a Jasio odpowiedział: "Użyłaś łącznika lub, który akceptuje zrobienie zarówno jednego, jak i drugiego, podobnie jak or
w programowaniu". Mama Jasia zaakceptowała to wyjaśnienie, więc poszedł on z kolegami do kina.
Operator not
Ostatnim operatorem logicznym, który powinniśmy poznać, jest zaprzeczenie, czyli not
przed wartością logiczną. Słowo "not" oznacza "nie". Podobnie jak -
(minus) przed liczbą zamienia jej znak na odwrotny, tak not
przed wartością logiczną zamienia ją na odwrotną. Operator negacji not
zamienia True
na False
, a False
na True
.
cond | !cond |
---|---|
True | False |
False | True |
print(not True) # False
print(not False) # True
is_amazing = True
print(not is_amazing) # False
is_boring = False
print(not is_boring) # True
# Podobnie jak przy liczbach
positive = 1
print(-positive) # -1
negative = -1
print(-negative) # 1
Programowanie akceptuje podwójne zaprzeczenie, co oznacza, że każdy kolejny znak zaprzeczenia odwraca wartość logiczną4.
print(True) # True
print(not True) # False
print(not not True) # True
print(not not not True) # False
print(not not not not True) # True
Operator negacji not
stawia się często w bardziej złożonym wyrażeniu przed pojedynczą zmienną. Jasio zrozumiał to wtedy, gdy jego mama powiedziała: "Będziesz mógł grać na komputerze, jeśli nie zawalisz sprawdzianu z matematyki i posprzątasz pokój". Wykorzystał on zaprzeczenie, by przełożyć to zdanie na język Python.
can_play_games = not failed_math_test and cleaned_room
Zwróć uwagę, że negacja odnosi się tutaj tylko do niezawalenia sprawdzianu. not True and False
zwraca False
, ponieważ najpierw not True
zwraca False
, a następnie False and False
zwraca False
. Podobnie jak przy liczbach -10 + 11
równe jest 1
, a nie -21
. Jeśli chcielibyśmy, aby zaprzeczenie negowało większy obszar wyrażenia, powinniśmy cały ten fragment otoczyć nawiasami. not (True and False)
zwraca True
, bo najpierw True and False
zwraca False
, które jest następnie negowane przez not
.
# Sprawdzian zaliczony
failed_math_test = False
# Pokój nieposprzątany
cleaned_room = False
# Nie zawaliłeś sprawdzianu i posprzątałeś pokój
print(not failed_math_test and cleaned_room) # False
# Nie jest tak, że
# zawaliłeś sprawdzian i posprzątałeś pokój
print(not (failed_math_test and cleaned_room)) # True
Czytanie wyrażeń logicznych
Warto poćwiczyć czytanie wyrażeń logicznych na głos. Ja zwykle robię to następująco:
and
czytam jako i.or
czytam jako lub.not
przed zmienną czytam jako nie, a przed nawiasem jako nie jest tak, że.
Poćwiczmy to na poniższych przykładach, dla zmiennych:
is_grounded
jako "ma szlaban"cleaned_room
jako "posprzątał pokój"passed_test
jako "zaliczył sprawdzian"
Przeczytaj poniższe zdania:
cleaned_room and passed_test
- posprzątał pokój i zaliczył sprawdzian.not is_grounded or passed_test
- nie ma szlabanu lub zaliczył sprawdzian.cleaned_room and not passed_test
- posprzątał pokój i nie zaliczył sprawdzianu.not (is_grounded or not passed_test)
- nie jest tak, że ma szlaban lub nie zaliczył sprawdzianu.not (not cleaned_room and not passed_test)
- nie jest tak, że nie posprzątał pokoju i nie zaliczył sprawdzianu. Jest to równoznaczne zcleaned_room or passed_test
.
not (not a and not b)
jest zawsze równoznaczne za or b
, anot (not a or not b)
jest równoznaczne za and b
. Takie obrócenia stosuje się, aby pozbyć się ciężkiego do przeczytania zaprzeczenia. Przykładowo, jeśli mielibyśmy waruneknot (has_computer and not is_grounded)
to moglibyśmy wykorzystać fakt, żenot (not a and not b)
toa or b
, i skrócić to wyrażenie donot has_computer or is_grounded
(not
przedis_grounded
zniknął, bonot not a
to po prostua
).
Ćwiczenie: Złożone wyrażenia logiczne
Co zostanie wypisane w wyniku działania poniższego kodu?
has_computer = True
passed_test = False
is_grounded = False
print(has_computer and passed_test)
print(passed_test or is_grounded)
print(has_computer and not passed_test)
can_play_games = has_computer and not is_grounded
print(can_play_games)
play_games = has_computer and can_play_games
if not passed_test:
is_grounded = True
print(play_games)
print(passed_test or not is_grounded)
print(not (not has_computer or not passed_test))
Odpowiedzi na końcu książki.
"and" po angielsku oznacza "i".
Precyzyjniej mówiąc, całe wyrażenie jest truthy, gdy obydwie strony są truthy, nie będę jednak rozwijał bardziej tego tematu.
"or" po angielsku oznacza "lub".
Bawiąc się językiem, możemy powiedzieć: nie jest tak, że programowanie nie akceptuje podwójnego zaprzeczenia. A nawet (nie nie nie nie) akceptuje wielokrotne zaprzeczenie.