cities = ["Tokyo","Shanghai","Jakarta","Seoul","Guangzhou","Beijing","Karachi","Shenzhen","Delhi"]
cities_not_start_s = [i for i in cities if i[0] != 'S']
print(cities_not_start_s)
# 출력값
['Tokyo', 'Jakarta', 'Guangzhou', 'Beijing', 'Karachi', 'Delhi']
population_of_city = [('Tokyo',36923000), ('Shanghai',34000000), ('Jakarta', 30000000), ('Seoul', 25514000),
('Guangzhou', 25000000), ('Beijing', 24900000), ('Karachi', 24300000), ('Shenzhen', 23300000), ('Delhi', 21753486)]
dict_city = {i:j for i, j in population_of_city}
print(dict_city)
# 출력값
{'Tokyo': 36923000, 'Shanghai': 34000000, 'Jakarta': 30000000, 'Seoul': 25514000, 'Guangzhou': 25000000,
'Beijing': 24900000, 'Karachi': 24300000, 'Shenzhen': 23300000, 'Delhi': 21753486}
D = {'a':1, 'b':2, 'c':3}
for key in D.keys():
print(key)
# while 문
D_2 = iter(D) # iter : 반복 가능한 데이터를 입력받아 반복자를 반환하는 함수
while True:
try:
key = next(D_2) # next : 반복자를 입력받아 다음 출력값을 반환하는 함수
except StopIteration:
break
print(key)
evaluation 은 값을 구함 이라는 뜻이다. lazy evaluation은 느리게 값을 구한다는 뜻. 어떤 값이 실제로 쓰일 때까지 그 값의 계산을 뒤로 미루는 동작 방식이다. 어떤 값이 필요할때만 사용하기 때문에 시간과 메모리를 절약할 수 있다.
import time
L = [1, 2, 3]
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)
# comprehension_list 를 출력해보았다.
comprehension_list=
sleep 1s
sleep 1s
sleep 1s
[1, 2, 3]
# print_iter(comprehension_list) 을 실행하면
comprehension_list=
sleep 1s # 1초 간격으로 출력된다
sleep 1s
sleep 1s
1 # 1 2 3 이 한번에 출력된다
2
3
# generator_exp 를 출력해 보았다
generator_exp=
<generator object <genexpr> at 0x102a8c190>
# print_iter(generator_exp) 를 실행하면
generator_exp=
sleep 1s # 1
1 # 2
sleep 1s # 2
2 # 3
sleep 1s # 3
3 # 4 순서로 출력된다
차이점은 위의 출력값만 보아도 알 수 있다.
리스트 컴프리헨션은 함수 lazy_return 을 먼저 실행해서 값을 출력하고 리턴값은 한번에 리스트로 만들었기 때문에 print_iter 함수를 실행하여 요소 하나씩을 출력했을 때 sleep 1s 는 1초씩 간격을 두고 출력되지만 1, 2, 3 은 한번에 출력된다. 수행하는 시간이 길거나 list값이 큰 경우에는 그만큼의 메모리가 늘어난다.
제너레이터는 실제로 값을 사용할 때 함수가 실행이 된다.
그래서 제너레이터 표현식을 출력하였을 때는 함수를 실행한 출력값이 나오지 않는다. print_iter 를 실행하면 그 때 하나씩 sleep_func 함수를 실행하며 값을 출력한다. 필요할 때만 실행할 수 있기 때문에 그만큼 메모리를 절약할 수 있다.
import types
print(dir(types))
## 출력값
['AsyncGeneratorType', 'BuiltinFunctionType', 'BuiltinMethodType', 'CellType', 'ClassMethodDescriptorType', 'CodeType',
'CoroutineType', 'DynamicClassAttribute', 'FrameType', 'FunctionType', 'GeneratorType', 'GetSetDescriptorType', 'LambdaType',
'MappingProxyType', 'MemberDescriptorType', 'MethodDescriptorType', 'MethodType', 'MethodWrapperType', 'ModuleType',
'SimpleNamespace', 'TracebackType', 'WrapperDescriptorType', '_GeneratorWrapper', '__all__', '__builtins__', '__cached__',
'__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_calculate_meta', '_cell_factory', 'coroutine',
'new_class', 'prepare_class', 'resolve_bases']
# 다음과 같이 비밀번호의 길이와 대문자가 포함된것을 확인하는 간단한 함수가 있습니다.
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 = [
lambda x: 'SHORT_PASSWORD' if len(x) < 8 else None,
lambda x: 'NO_CAPITAL_LETTER_PASSWORD' if not any((i.isupper()) for i in x) else None
]
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