Python - 논리 연산

1. and / or

and 연산 : 하나만 False여도 전체가 False

or 연산 : 하나만 True여도 전체가 True

logic.py

a = 10
if a < 0 and 2 ** a > 1000 and a % 5 == 2 and round(a) == a:
    print("복잡한 식")
  • and는 주어진 값이 모두 True 여야 하는 연산이다.
  • 맨 앞에 있는 식 a<0False이므로 뒷 부분은 볼 필요가 없다.
  • 좌우 모두 True여야 하는데 하나라도 False면 전체가 ` False`이기 때문이다.
  • 논리식이 틀렸으므로, print문이 실행되지 않는 것이다.
  • or 연산도 마찬가지이다. or 연산으로만 이루어진 식은 하나만 True면 전체가 True이다.

2. ‘항상 False를 반환하는 함수’

파이썬은 and연산or연산의 특징을 적극 활용한다.

:: test 1

# 항상 False를 반환하는 함수
def return_false():
    print("함수 return_false")
    return False

# 항상 True를 반환하는 함수
def return_true():
    print("함수 return_true")
    return True

print("테스트 1")
a = return_false()
b = return_true()

if a and b: # a와 b가 모두 True면
    print(True)
else:       # 그렇지 않으면
    print(False)

logic.py

테스트 1
함수 return_false
함수 return_true
False
  • 순서대로 print문이 출력되고 마지막에 a and b의 결과는 False가 나왔다.
  • a False 이므로 else블록이 실행되었다.

:: test 2

# 항상 False를 반환하는 함수
def return_false():
    print("함수 return_false")
    return False

# 항상 True를 반환하는 함수
def return_true():
    print("함수 return_true")
    return True

print("테스트 2")
if return_false() and return_true():
    print(True)
else:
    print(False)
  • 앞의 예제인 테스트 1과 다른 점은 return_false()return_true()의 결과를 각각 ` 변수 a와 b에` 넣어 비교했는가, 비교하지 않았는가 이다.

  • 실행해 보면 결과가 조금 다르다.

logic.py

테스트 2
함수 return_false
False
  • 파이썬에서는 andor 연산을 할때 첫번째 값을 보고 더 이상 실행할 필요가 없으면 두 번째 값은 실행하지 않는다. 이를 ‘단락(short-circuit) 평가’라고 합니다.
  • 예를 들어, 다음과 같은 and연산에서 첫 번째 조건식의 결과가 False이면 뒤에 있는 조건식은 불필요하다.

3 . 단락(short-circuit) 평가

dic = {"key2":"Value1"}
if "key1" in dic and dic["key1"] == "Value1":
    print("key1 도 있고, 그 값은 Valu1이네")
else:
    print("아니네")

logic.py

아니네

하지만 이 코드는 단락평가를 하지 않는다면 에러가 발생할 수 있는 코드 이다.

if문의 순서를 바꾸면

dic = {"key2":"Value1"}
if dic["Key1"] == "Value1" and "Key1" in dic:
    print("key1 도 있고, 그 값은 Valu1이네")
else:
    print("아니네")

logic.py

KeyError                       Traceback (most recent call last)
<ipython-input-13-1ed243192a80> in <module>()
----> 1 if dic["Key1"] == "Value1" and "Key1" in dic:
      2     print("Key1도 있고, 그 값은 Value1이네")
      3 else:
      4     print("아니네")
      5

KeyError: 'Key1'

조건식 안에 "Key1"을 가지고 "value1"의 값을 비교하려고 하는데 "key1"dic 안에 없다.

그래서 keyError가 발생했다. 이 코드는 실행되는 순간 오류가 발생한다.

하지만 "key1" in dic 을 먼저 검사한다면 "key1"dic 에 없으므로 else문 으로 넘어가 아니네 를 출력한다.

단락 평가를 하지 않으면 , 다음과 같이 key1dic에 있는지 먼저 검사하고, 다음으로 Value1을 검사하는 중첩 if문을 써야 한다.

if "Key1" in dic:
    if dic["Key1"] == "Value1":
        print("Key1도 있고, 그 값은 Value1이네")

그러나 파이썬은 단락 평가를 지원하기에 한 줄로도 쓸 수 있다.

if "Key1" in dic and dic["Key1"] == "Value1":
    print("Key1도 있고, 그 값은 Value1이다")
else:
	print("아니네")

4. bool 값과 논리연산

In [15]: bool(0) # 0을 넣으면 False
Out[15]: False

In [16]: bool(1)
Out[16]: True

In [17]: bool(-1) # 양수든 음수든 모두 True
Out[17]: True

In [19]: bool([]) # 빈 리스트를 넣으면 False
Out[19]: False

In [20]: bool([3]) # 값을 넣으면 True
Out[20]: True

In [21]: bool(None) # 빈 값(None)을 넣으면 False
Out[21]: False

In [22]: bool("") # 빈 문자열을 넣으면 False
Out[22]: False

In [23]: bool("hi") # 빈 문자열이 아니면 True
Out[23]: True

In [24]: if "Hi":
    ...:     print('hello')
    ...:
hello

In [25]: if "":
    ...:     print("hello")  # 빈 문자열을 넣으면, 출력되지 않는다. 
    ...:

단락평가와 결합하면 유용하다.

A and B A or B
A가 False면 단락 평가에 의해 B는 검사하지 않고 종료된다. 전체 식은 무조건 A 값에 따라 False가 된다.A가 True면 무조건 B 값을 따른다. A가 True면 단락 평가에 의해 B는 검사하지 않고 종료된다. 전체 식은 무조건 A 값에 따라 True가 된다.A가 False면 무조건 B 값을 따른다.

bool_test.py

Value = input("입력해 주세요>") or "아무것도 못받았어"
print("입력받은 값>", Value)
python bool_test.py

입력해 주세요> 안녕
입력받은 >  안녕

python bool_test.py
입력해 주세요>
입력받은 > 아무것도 못받았어

input이 비어 있으면 input('입력해 주세요>')의 값은 False입니다. 앞부분이 False면 전체 식은 무조건 뒷부분('아무것도 못 받았어')의 결과를 따릅니다.

뒷부분이 True인지 False인지에 따라 전체 식이 결정되므로 값이 아무것도 못 받았어가 되는 것입니다.

input안녕이라고 입력하면 앞부분이 안녕이므로 뒷부분을 볼 것도 없이 앞의 값을 따르는 것입니다. 실행 결과를 다시 한 번 보면 이해하기가 훨씬 쉬울 것입니다.

다음 코드는 어느 if문 안의 코드가 실행될까?

bool_test1.py

if []:
	print("[]은 True입니다.")

if [1, 2, 3]:
	print("[1,2,3]은/는 True입니다.")

if {}:
	print("{}은 True입니다.")

if {'abc': 1}:
	print("{'abc':1}은 True입니다.")

if 0:
	print("0은/는 True입니다.")

if 1:
	print("1은 True입니다.")

실행 결과

[1,2,3]/ True입니다.
{'abc':1} True입니다.
1 True입니다.

bool_test2.py

a = 1 or 10	# 1의 bool 값은 True입니다.
b = 0 or 10	# 0의 bool 값은 False입니다.

print("a:{}, b:{}".format(a, b))

or연산의 결과는 앞의 값이 True이면 앞의 값을, 앞의 값이 False이면 뒤의 값을 따릅니다.

실행 결과

a:1, b:10