Pythonic Code
Python 에서 주로 많이 쓰는 파이썬스러운 코딩 기법
파이썬 특유의 문법을 활용하여 효율적으로 코드를 표현
why Pythonic Code?
Split & Join
items = "zero one two three"
items.split(" ")
>>> ['zero', 'one', 'two', 'three']
# unpacking
example = "temlab.technology.io"
subdomain, domain, tld = example.split(".")
print(subdomain)
>>> 'teamlab'
List comprehension
result = [i for i in range(10)]
>>> [0,1,2,3,4,5,6,7,8,9]
result = [i for i in range(10) if i % 2 == 0]
>>> [0,2,4,6,8]
# Nested For loop
word_1 = "Hello"
word_2 = "World"
result = [i+j for i in word_1 for j in word_2] # 이중 for문과 같음
case_1 = ["A","B","C"]
case_2 = ["D","E","A"]
result = [i+j for i in case_1 for j in case_2 if not(i==j)] # 이중 for문에 조건까지 포함
# i와 j가 같지 않으면 i+j, 같을 경우는 i만
result = [i+j if not(i==j) else i for i in case_1 for j in case_2]
# 24글자가 모두 포함되어 있는 문장이라 자주 보인다
words = 'The quick brown fox jumps over the lazy dog'.split()
# list의 각 elemente들을 대문자, 소문자, 길이로 변환하여 two dim list로 변환
stuff = [[w.upper(), w.lower(), len(w)] for w in words]
# 옆으로 쭉 출력되서 보기 힘든 경우 pprint를 사용하면 깔끔하게 보인다
pprint.pprint(stuff)
Two dimensional vs One dimensional
# One dimensional
result = [i+j for i in case_1 for j in case_2]
# Two dimensional
# 뒤의 for문이 일반적인 for loop의 맨 위 for문과 같다
result = [[i+j for i in case_1] for j in case_2]
Enumerate
for i , v in enumerate("ABC"):
print("{0} \t {1}".format(i,v))
Zip
alist = ["a1","a2","a3"]
blist = ["b1","b2","b3"]
[[a,b] for a,b in zip(alist,blist)]
>>> [['a1','b1'],['a2','b2'],['a3','b3']]
# 번호와 각 리스트의 값을 병렬적으로 함께 추출 가능
for i , v in enumerate(zip(alist,blist)):
print(i, v)
Lambda
# lambda 바로 뒤에는 parameter 값, : 뒤에 return이 되는 값을 작성
f = lambda x, y : x + y
Map
ex = [1,2,3,4,5]
f = lambda x: x ** 2
list(map(f,ex))
>>> [1,4,9,16,25]
Reduce
from functools import reduce
# 1과 2를 더한 값 3이 다음번 x가 되고, 3과 4를 더하여 다음 x가 되는 구조
print(reduce(lambda x,y : x+y, [1,2,3,4,5]))
💡 Lambda , map, reduce는 간단한 코드로 다양한 기능을 제공하지만, 코드의 직관성이 떨어져서 권하지는 않는 방식임
💡 하지만 다양한 머신러닝 코드에서는 여전히 많이 사용 중
iterable objects
cities = ["Seoul", "Busan", "Jeju"] # 메모리에 올리기
iter_obj = iter(cities) # 메모리 주소 가져오기
print(next(iter_obj)) # 다음의 메모리주소의 값 가져오기
print(next(iter_obj))
print(next(iter_obj))
Generator
# 일반적인 리스트
def general_list(value):
result = []
for i in range(value):
reuslt.append(i)
return result
# 주소만 가지고 있는 상태
def generator_list(value):
reuslt = []
for i in range(value):
yield i # yield 를 통해 값을 호출
# 값 호출
for a in generator_list(50):
print(a)
Generator comprehension
gen_ex = (n*n for n in range(500)) # [] 대신 () 사용
print(type(g))
when generator
passing arguments
함수에 argument를 넘기는 방법은 다양하다
keyword arguments
def print_somthing(my_name,your_name):
print("Hello {0}, My name is {1}".format(your_name,my_name))
print_somthing("Sungchul", "TEAMLAB")
print_somthing(your_name="TEAMLAB",my_name="Sungchul") # 변수명 사용
def print_somthing(my_name,your_name="TEAMLAB"): # 기본값 입력
print("Hello {0}, My name is {1}".format(your_name,my_name))
print_somthing("Sungchul", "TEAMLAB")
print_somthing("Sungchul")
함수의 paraemter가 정해져 있지 않을 때 가변인자를 사용
가변인자는 일반적으로 *args를 변수명으로 사용
기존 parameter를 제외하고 나오는 값을 tuple로 저장
def asterisk_test(a,b,*args):
return a+b+sum(args)
print(asterisk_test(1,2,3,4,5)) # 1:a , 2:b ,나머지는 *args에 tuple형태로 들어감
# unpacking도 가능
def asterisk_test(*args):
x, y, z = args
return x, y, z
asterisk_test(1,2,3)
def kwargs_test_1(**kwargs):
print(kwargs)
kwargs_test_1(first=3, second=4, third=5) # key, value 형태의 dict type으로 그대로 출력
def kwargs_test_2(one,two=2,*args,**kwargs):
print(one+two+sum(args)) # 69
print(args) #(3,5,6,7,8)
print(kwargs)
# one:10, two:30, args:(3,5,6,7,8), 나머지 kwargs
# two는 default 값이 있지만 무시
kwargs_test_2(10,30,3,5,6,7,8,first=3, second=4, third=5)
asterisk
단순 곱셈, 제곱연산, 가변 인자 활용, unpacking a container 등 다양하게 사용된다
unpacking a container