List comprehension
1.다음과 같은 도시목록의 리스트가 주어졌을때, 도시이름이 S로 시작하지 않는 도시만 리스트로 만들 때 리스트 컴프리헨션을 사용하여 함수를 작성해 보세요.
cities = ["Tokyo", "Shanghai", "Jakarta", "Seoul", "Guangzhou", "Beijing", "Karachi", "Shenzhen", "Delhi" ]
2.다음과 같은 도시, 인구수가 튜플의 리스트로 주어졌을때, 키가 도시, 값이 인구수인 딕셔너리를 딕셔너리 컴프리헨션을 사용한 함수를 작성해 보세요.
population_of_city = [(‘Tokyo', 36923000), (‘Shanghai', 34000000), (‘Jakarta', 30000000), (‘Seoul', 25514000), (‘Guangzhou', 25000000), (‘Beijing', 24900000), (‘Karachi', 24300000 ), ( ‘Shenzhen', 23300000), (‘Delhi', 21753486) ]
Iterator
이터레이터는 값을 순차적으로 꺼내올 수 있는 객체 입니다.
L이라는 다음 리스트가 있을때 for loop문으로 값마다 제곱을 하는 코드는 다음과 같습니다.
L = [1, 2, 3]
for x in L:
print(x ** 2, end=' ')
L 리스트가 반복 가능한 객체인지 확인해보는 방법은 dir 로 호출하여 iter 함수가 있는지 확인해볼 수 있습니다.
그럼 이제 파이썬 기본함수는 중에 앞에서 알아본 iter함수와 next함수를 편하게 사용하게 해주는 iter와 next에 대하여 알아 보겠습니다. iter는 객체의 iter 함수를 호출해주고 next는 객체의 next 함수를 호출하는 함수 입니다. 위의 L 리스트에 iter와 next를 적용해서 for loop 으로 제곱한 것을 while문으로 구현해보겠습니다.
I = iter(L)
while True:
try:
X = next(I)
except StopIteration:
break
print( X**2, end=" ")
딕셔너리도 반복가능한 객체라서 앞서본 리스트와 같이 iter함수와 next함수를 사용할 수 있고 파이썬 기본함수인 iter, next 또한 사용할 수 있습니다. 다음의 간단한 키를 출력하는 딕셔너리에 대한 for 문을 while문으로 구현해 보세요.
D = {'a':1, 'b':2, 'c':3}
for key in D.keys():
print(key)
Generator
파이썬에서 보통의 함수는 값을 반환하고 종료 하지만 제너레이터 함수는 값을 반환하기는 하지만 산출(yield)한다는 차이점이 있습니다. 그리고 제너레이터는 쉽게 얘기하면 이터레이터를 생성해주는 함수라고도 볼 수 있습니다.
이번 과제는 다음코드를 실행해보고 분석한 결과를 블로깅하는 과제 입니다. lazy evaluation 이란 무엇인지와 장점 및 리스트 컴프리헨션과의 차이점에 대하여 블로깅 해주세요.
import time
def print_iter(iter):
for element in iter:
print(element)
def lazy_return(num):
print("sleep 1s")
time.sleep(1)
return num
print("comprehension_list=")
comprehension_list = [ lazy_return(i) for i in L ]
print_iter(comprehension_list)
print("generator_exp=")
generator_exp = ( lazy_return(i) for i in L )
print_iter(generator_exp)
lambda
람다는 인라인 함수를 정의할 때 사용하며 익명 함수(anonymous functions) 또는 람다 표현식(lambda expression)이라고 부릅니다.
람다 표현식도 nested 될수 있고 다소 복잡한 구조를 가질 수 있지만 람다의 가장 일반적인 형식은 다음과 같습니다.
lambda argument1, argument2, ... argumentN : expression using arguments
그럼 람다의 간단한 실제 예제를 보도록 하겠습니다.
f = lambda x,y,z : x+y+z
print(f) # <function <lambda> at 0x10343e710>
print(f(1,2,3))
여기서 x,y,z 는 argument1, 2, 3 에 해당하고 expression 은 x+y+z 입니다. 따라서 간단하게 테스트해보면 function 로 출력되는 것을 확인할 수 있고 실제 함수처럼 인자를 입력해서 호출해보면 1,2,3을 더한 6이 출력되는 것을 확인할 수 있습니다. 그리고 람다는 다음과 같이 무조건 함수로 다시 작성 할 수 있습니다.
def add_func(x,y,z):
return x+y+z
함수로 다시 작성한 함수를 보면 람다에 한줄로 return x+y+z 를 쓸 수 있을 것 같지만 람다는 표현식이므로 return을 사용할 수 없습니다.
람다는 무조건 함수로 만들 수 있는데 그럼 언제 유용하게 사용할 수 있을까요 ?
다음과 같은 간단한 인라인 콜백함수를 만들거나 함수안에서 복잡한 처리를 할 수 없을 때 유용하다고 할 수 있습니다. 콜백함수란 어떤 이벤트가 발생했을때 호출되는 함수인데 콜백함수가 여러블록으로 구성된 실행문이 아니고 다른 컴포넌트에서 사용되지 않는다면 해당 컴포넌트만을 위한 람다 표현식이 적절할 것 입니다.
다음과 같은 어떤 정수에 2제곱, 3제곰, 4제곱을 하는 예제에서 함수로 구현하는 것보다 람다로 구현하는 것이 낫겠죠?
Lambdas = [
lambda x : x ** 2,
lambda x : x ** 3,
lambda x : x ** 4
]
for lambda_func in Lambdas:
print( lambda_func(2) )
이것을 함수로 구현하면 다음과같이 구현할 수 있지만 간단함 함수임에도 함수이름을 만들어야하고 다른 함수이름과 충돌이 발생할 가능성이 있을 수 있습니다. 딱 봐도 람다 표현식을 사용한 코드가 깔끔하죠 ? 이렇게 람다는 함수가 사용되는 위치에 인라인 표현식으로 대체되는 경우 간편한 방법을 제공합니다.
def square(x):
return x ** 2
def power_3(x):
return x ** 3
def power_4(x):
return x ** 4
powers = [ square, power_3, power_4 ]
for f in powers:
print( f(2) )
import types
f = lambda x,y,z : x+y+z
print(f)
print(type(f))
print( type(f) == types.LambdaType)
(출처:파이썬 공식문서)
def check_password(password):
if len(password) < 8:
return 'SHORT_PASSWORD'
if not any(c.isupper() for c in password):
return 'NO_CAPITAL_LETTER_PASSWORD'
return True
이함수에 있는 if문 두개를 람다표현식을 이용하여 다음과 같은 형식으로 작성해 보세요.
아래의 lambdas 리스트안에 두개의 람다표현식을 작성해야하며 주석으로 표시된 프린트가 출력결과로 나와야 합니다.
lambdas = [
]
def check_password_using_lambda(password):
for f in lambdas:
if f(password) is not None:
return f(password)
return True
print( check_password_using_lambda('123') ) # SHORT_PASSWORD
print( check_password_using_lambda('12356789f') ) # NO_CAPITAL_LETTER_PASSWORD
print( check_password_using_lambda('123456789fF') ) # True