컴프리헨션은 실제 프로그래밍에서 한 줄로 파이썬 기능을 구현할 수 있는 기능이다.
코드간소화를 위해서 사용되고 직관적이며 속도도 빠르다.
조건이 복잡해지는 경우에는 직관성이 떨어지고, 메모리 사용량이 증가하여 사용하기가 어렵다.
numbers = [1, 2, 3, 4]
squares = []
for n in numbers:
squares.append(n**2)
print(squares) # [1, 4, 9, 16]
numbers = [1, 2, 3, 4]
squares = [n**2 for n in numbers]
print(squares) # [1, 4, 9, 16]
list_a = [1, 2, 3, 4]
list_b = [2, 3, 4, 5]
common_num = []
for a in list_a:
for b in list_b:
if a == b:
common_num.append(a)
print(common_num) # [2, 3, 4]
list_a = [1, 2, 3, 4]
list_b = [2, 3, 4, 5]
common_num = [a for a in list_a for b in list_b if a == b]
print(common_num) # [2, 3, 4]
# 딕셔너리 컴프리헨션
test = {'A': 5, 'B': 7, 'C': 9, 'D': 6, 'E': 10}
test = {na:test for na,test in test.items() if na != 'E'}
print(test) # {'A': 5, 'B': 7, 'C': 9, 'D': 6}
# 아래와 같이 조건을 반복문 대신 조건을 먼저 쓸 수 있다.
# 조건을 위해 if를 사용하는 경우 else를 작성해줘야된다.
pas = {name: 'PASS' if numbers > 8 else 'NO PASS' for name, numbers in numbers.items()}
print(pas) # AttributeError: 'list' object has no attribute 'items'
# 아래처럼 반복문을 연속으로 작성가능하다.
# set은 특성상 중복값을 제외한다.
print('list for loop : ',[n for n in range(1, 5+1) for n in range(1, 5+1)]) # list for loop : [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
print('set for loop : ',{n for n in range(1, 5+1) for n in range(1, 5+1)}) # list for loop : [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
# 두개의 리스트를 하나의 딕셔너리로 합침.
# 하나는 key, 또 다른 하나는 value로 사용한다
subjects = ['math', 'history', 'english', 'computer engineering']
scores = [90, 80, 95, 100]
score_dict = {key: value for key, value in zip(subjects, scores)}
print(score_dict) # {'math': 90, 'history': 80, 'english': 95, 'computer engineering': 100}
# 튜플 리스트를 딕셔너리 형태로 변환
score_tuples = [('math', 90), ('history', 80), ('english', 95), ('computer engineering', 100)]
score_dict = {t[0]: t[1] for t in score_tuples}
print(score_dict) # {'math': 90, 'history': 80, 'english': 95, 'computer engineering': 100}
코드가 복잡해지거나 기능이 많아지는 경우, 변수사용에 따라 함수 및 클래스의 접근이 달라진다.
변수이름설정, 변수활용도에 따른 변수설계가 중요하다.
지역변수 : 해당 변수가 포함된 함수 안에서만 수정하고, 읽을 수 있다.
일반 전역변수 : 하나의 파이썬 파일전체에서 값을 읽을 수 있다. 되도록이면 함수 안에서 사이드이펙트 및 가독성을 위해 값을 수정하지 않도록 한다.
global 전역변수 : 일반 전역변수와 다른 점은 변수가 생성되는 시점만 다르다.
지역변수는 이름이 같더라도, 소속된 함수가 다르면 다른 변수로 취급된다.
전역변수는 하나의 파이썬파일에 있는 모든 함수에 쓰일 수 있다.
# 아래 소스코드를 한 줄씩 실행하면서 지역변수와 전역변수에 대해 파악한다.
g_var = 'g_var' # 전역변수
# 값 수정후(수정값)
def variables():
global glo_var # global 전역변수
glo_var = 'glo_var' # global 전역변수에 새로운 값 할당
lo_var = 'lo_var' # 지역변수
print()
print('(값 수정후)함수 안에서 g_var(전역변수) : ', g_var) # 수정되지 않고 초기값을 출력함
print('(값 수정후)함수 안에서 glo_var(global 전역변수) : ', glo_var) # 함수에서 수정된 후 값을 출력함
print('함수 안에서 lo_var(지역변수) : ', lo_var) # 특정 함수에서만 출력되는 지역변수
# 전역변수를 파라미터로 담은 함수
def second_variables(glo_var,g_var):
glo_var = 'glo_var in second_variables()'
g_var = 'g_var in second_variables()'
lo_var = 'second lo_var'
print('서로 다른 함수에서 지역변수이름이 같은 경우 :',lo_var)
return glo_var,g_var
# 값 수정전(초기값)
g_var = 'g_var_new_value'
glo_var = 'glo_var_new_value'
print('(값 수정전)함수 밖에서 g_var(전역변수) : ', g_var)
print('(값 수정전)함수 밖에서 glo_var(global 전역변수) : ', glo_var) # 새로 할당된 값으로 수정됨
# print('함수 밖에서 lo_var(지역변수) : ', lo_var) # 특정 함수 안에서만 사용하는 지역변수이므로 출력안됨
# 전역변수의 값 수정
#print('함수의 파라미터가 전역변수인 경우 :', second_variables(glo_var, g_var))
# 지역변수를 갖고 오는 경우
#print('함수의 파라미터가 지역변수인 경우 :', second_variables(glo_var, lo_var))
# 함수에서 수정된 전역변수 재호출
print('전역변수값 :',glo_var, g_var)
variables()
# (값 수정전)함수 밖에서 g_var(전역변수) : g_var_new_value
# (값 수정전)함수 밖에서 glo_var(global 전역변수) : glo_var_new_value
# 전역변수값 : glo_var_new_value g_var_new_value
# (값 수정후)함수 안에서 g_var(전역변수) : g_var_new_value
# (값 수정후)함수 안에서 glo_var(global 전역변수) : glo_var
# 함수 안에서 lo_var(지역변수) : lo_var
생각하는 시간 : 예외처리는 어떻게 사용될까?
실제 대규모 서비스에서 공동작업을 진행하는 경우, 예외처리를 하는 것이 중요하다.
파이썬에서는 루프가 반복 수행하는 내부 구문 바로 다음에 if 없이도 else 구문을 추가할 수 있다.
for~else 구문에서는 break에 따라 수행여부가 달라진다.
if/else 구문에서 else는 '앞의 구문이 수행되지 않으면 else구문을 수행하시오' 라는 뜻이다.
try/except 구문 또한 이 구문 앞의 try 구문을 수행하다가 예외발생 시, except 구문을 수행하시오' 라는 뜻이다.
for i in range(3):
print('loop : ', i) # 1) 루프반복수행
else :
print('Else statement') # 2) else 구문 추가수행
# loop : 0
# loop : 1
# loop : 2
# Else statement
# 그렇다면 break문이 있다면?
for i in range(3):
print('loop : ', i) # 1) 루프반복수행
if i == 1:
break # break는 어떤 영향을 줄 것인가?
else :
print('Else statement') # 2) else 구문 추가수행
# loop : 0
# loop : 1
# 반복문에 빈 리스트를 넣으면 어떻게 될까?
for i in []:
print('loop : ', i) # 1) 루프반복수행
else :
print('Else statement') # 2) else 구문 추가수행
# Else statement
# 반복문이 while 형태로 False인 경우에는 어떨까?
while False:
print('loop : ', i) # 1) 루프반복수행
else :
print('Else statement') # 2) else 구문 추가수행
# Else statement
# 서로소 판별문제
p_a = 5
p_b = 3
for i in range(2, min(p_a, p_b) +1):
print('testing ....', i)
if p_a % i == 0 and p_b % i == 0:
print('서로소가 아닙니다.')
break
else:
print('서로소입니다.')
# testing .... 2
# testing .... 3
# 서로소입니다.
# for~else 예시
for i in []:
print('실행안됨')
else:
print('실행되면 안됨')
# 실행되면 안됨
# while~else 예시
while False:
print('실행안됨')
else:
print('실행되면 안됨')
# 실행되면 안됨
# 첫번째방법. 조건에 맞는 경우, 함수에서 부울값을 반환해주는 방법
def bool_return(v1, v2):
for i in range(2, min(v1, v2) +1):
if v1 % i == 0 and v2 % i == 0:
return False
return True
# 조건점검
#assert bool_return(4,9), '서로소입니다.'
#assert bool_return(3,6), '코드 점검 메시지입니다.'
assert not bool_return(3,6), '서로소 아닙니다.'
print('bool_return:',bool_return(4,9)) # 디폴트값 반환
# bool_return: True
# 두번째방법. 조건에 맞는 경우, 함수에서 결과값 변수를 반환해주고 break로 빠져나온다.
def variable_return(p_a, p_b):
is_variable = True
for i in range(2, min(p_a, p_b) +1):
if p_a % i == 0 and p_b % i == 0:
is_variable = False
break
return is_variable
# 조건점검
assert variable_return(4,9), '서로소입니다.'
#assert variable_return(3,6), '코드 점검 메시지입니다2.'
assert not variable_return(3,6), '서로소 아닙니다.'
print('variable_return:',variable_return(4,9)) # 변수값 반환
# variable_return: True
def try_finally_ex(filename):
print('function start') # right case / error case, 1
handle = open(filename, encoding='utf-8')
try:
print('try test') # right case , 2
raise NotImplementedError
print('raise test')
return handle.read()
except FileNotFoundError:
print('file except') # right case
else:
print('file else')
finally:
print('finally call') # right case, 3
handle.close
filename = 'a.txt' # right case
#filename = 'b.txt' # error case
try_finally_ex(filename) # error case, 4
# try / except
try:
print(3/0)
except:
print('except case')
# except case
# try / except
try:
print(5/0)
except ZeroDivisionError:
print('except case ZeroDivisionError')
# except case ZeroDivisionError
# try / except
try:
print(7/0)
except ZeroDivisionError as e:
print(e)
# division by zero
# try / except / else
try:
print(3/1)
except:
print('except case')
else:
print('else case')
# 3.0
# else case
# try / except / finally
try:
print(5/0)
except:
print('except case')
finally:
print('finally case')
# except case
# finally case
# try / except / finally
try:
print(5/0)
print(try test)
except NameError as n:
print(n)
except ZeroDivisionError as z:
print(z)
pass
# SyntaxError: invalid syntax
# try / raise / except
try:
print('try test')
test = int(input())
if test < 0:
raise NotImplementedError # 예외사항에 대해 처리하는 raise!
print('test2 : ',test)
except NotImplementedError:
print('NotImplemented Error')
# None을 return 하는 경우
def none_test(num1, num2):
try:
return num1 / num2
except ZeroDivisionError:
return None # None 반환
# 문제없음, 단순히 None이 있는지 없는지 판단함
# result = none_test(0,2)
# print(result)
if result is None:
print('result is None')
# 문제발생
result = none_test(0, 2)
print(result)
# 조건식에서 not을 활용하는 경우, 파이썬에서는 None, 빈문자열, 빈리스트, 0을 모두 False로 판단한다
# 단순히 결과값이 0인데도 not result 조건으로 인해 False 처리된다.
# if not result:
# print('not result')
# 0.0
# None을 return 하지 않는다.
def not_none_return(num1, num2):
try:
return num1 / num2
except ZeroDivisionError as z:
raise ValueError('숫자 입력값이 잘못된 경우') from z
else:
print(result)
try:
#result = not_none_return(2, 0) # case 1 - 정상적으로 except 처리
#result = not_none_return(0, 2) # case 2 - 값 반환
except ValueError:
print('숫자 입력값이 잘못된 경우') # None을 반환하는 대신 예외를 발생시킨다.
else:
print(result)