Pythonic Code 기법 이어서!!
Step 1은 아래 글에!!
Pythonic Code #1 (split, join, list comprehension, enumerate, zip)
[Pythonic Code] - 파이썬 스타일의 코딩기법이다. - 파이썬 특유의 문법을 활용하여 효율적인 코드를 작성 가능하다. - 고급 코드를 작성할 수록 더 많이 필요해진다. * 주요 기법 split and join list compre
emilia.tistory.com
f) Lambda
- 함수 이름 없이 함수처럼 쓸 수 있는 익명함수
- 수학의 람다 대수에서 유래
- f = lambda x,y: x+y
- (lambda x,y: x+y)(10,50)
- print(f(1,4))
##### Lambda Ex
f = lambda x,y: x+y
print(f(1,4))
#출력
# 5
f = lambda x: x**2
print(f(3))
#출력
# 9
(lambda x,y: x+y)(10,50)
#출력
# 60
up_low = lambda x: x.upper() + x.lower()
up_low('My Happy')
#출력
# 'MY HAPPYmy happy'
g) Map
- sequence 자료형의 각 element에 동일한 function을 적용시켜준다.
- 두 개 이상의 list에도 적요이 가능하다.
- if filter 사용 가능하다.
##### Map Ex
#method1 - list로 변환
ex = [1,2,3,4,5]
f = lambda x:x**2
print(list(map(f,ex)))
#출력
# [1, 4, 9, 16, 25]
#method2 - 값 하나하나 출력
for value in map(f,ex):
print(value)
result = map(f,ex)
result
#출력
1
4
9
16
25
##### Map + List Comprehension
ex = [1,2,3,4,5]
list(map(lambda x:x**2 if x%2==0 else x, ex))
#출력
# [1, 4, 3, 16, 5]
#####Only List Comprehension
ex = [1,2,3,4,5]
print( [value**2 if value%2==0 else value for value in ex])
#출력
# [1, 4, 3, 16, 5]
위 처럼 map function 은 굳이 써주지 않아도 List Comprehension 만으로도 같은 출력을 낼 수 있다.
list comprehension 내의 for문으로 map을 쓰지 않고도 sequence자료형의 데이터들을 모두 사용해 원하는 값으로 도출할 수 있는 것이다.
h) Reduce
- list에 똑같은 함수 적용해서 결과를 통합한다.
- lamda function 을 작용시키는데 필요한 변수 수보다 입력 값의 개수가 작아선 안된다.
##### Reduce Ex
from functools import reduce #reduce function setup
a = reduce(lambda x,y: x+y, [1,2,3,4,5])
print(a)
#출력
# 15
*map and reduce function
파이썬 측에서도 사용 하지 않을 것을 권장한다.
- 문법이 어렵다.
- 테스트가 어렵다.
- 문서화 docstring 지원이 미비하다.
- 코드 해석이 어렵다.
- 이름이 존재하지 않는 함수의 출현으로 일관성 떨어진다.
- 그래도 아직은 쓰이긴 한다
ref) http://www.python.org/dev/peps/pep-0008/
i) Iterator & Iterable objects
- sequence 형 자료형에서 데이터를 순서대로 추출하는 object
: list/ tuple/string
- iter()와 next()의 함수로 iterable object를 iterator object로 사용한다.
##### Iterable object Ex
cities = ['Seoul','Busan','Jeju']
iter_obj = iter(cities)
print(iter_obj)
#출력
# <list_iterator object at 0x7fdfdd4d5490>
#메모리 주소만 가지고 있다.
#출력 방법1 : next()로 iterator object 사용
#출력 방법2 : for 문으로 iterator object 출력
#method1 : next()
next(iter_obj)
#출력
# 'Seoul'
#method2 : for loop
for value in iter_obj:
print(value)
#출력
Seoul
Busan
Jeju
j) Generator
- iterable object를 특수한 형태로 사용하는 함수이다.
- element가 사용되는 시점에 값을 메모리에 반환한다.
- list로 한번에 메모리에 올릴 수 있다.
- list(gen_ex) 형태를 활용해 메모리에 올린다.
- yield 를 이용해 값을 여러 개로 나누어서 출력이 가능하다.
* Generator + list comprehension
- list comprehension 과 유사한 형태로 generator 형태의 list를 생성할 수 있다.
- generator expression 이라는 이름으로 불린다.
- [] 대신 ()을 사용한다.
- 즉, list comprehension 형태인데 []대신 ()가 쓰여있다면 generator 형태인 것이고
- list function 을 활용해야 메모리에 올려진다는 점.
* Why Generator ?
- iterator는 generator에 반해 훨씬 큰 메모리 용량을 사용한다.
- 필요할 때만 올리는 방식으로 하기엔 generator 가 필요하다.
* When Generator !
- list 타입의 데이터를 반환해주는 함수는 generator 로 만들자.
: 읽기 쉽다는 장점
- 큰 데이터 처리시 generator 를 고려하자.
: 데이터가 커져도 처리의 어려움이 없다.
- 파일 데이터 처리시 generator 를 쓰자.
##### Yield Generator Ex
def generator_list(value):
result = []
for i in range(value):
yield i
generator_list(10)
next(generator_list(10))
#출력
# 0
#next 로 값 확인. next 해줄 때마다 다음 값 출력.
##### Yield Generator Ex
def gen_ex() :
n=1
print('first')
yield n
n+=1
print('second')
yield n
n+=1
print('last')
yield n
for item in gen_ex():
print(item)
list(gen_ex())
#출력
first
1
second
2
last
3
first
second
last
[1, 2, 3]
##### Generator + List Comprehension Ex
gen_ex = (n*n for n in range(10)) #[] 말고 ()사용
for value in gen_ex:
print(value)
print(type(gen_ex)) #<class 'generator'>
#출력
0
1
4
9
16
25
36
49
64
81
<class 'generator'>
##### Generator and list comprehension Memory size comparison
from sys import getsizeof
#generator
gen_ex = (n*n for n in range(500))
print(getsizeof(gen_ex)) #generator size
print(getsizeof(list(gen_ex))) #generator->list size
#출력
# 112
# 4216
#list comprehension
list_ex = [n*n for n in range(500)]
print(getsizeof(list_ex)) #list size
#출력
# 4216
위와 같이 generator 상태의 메모리 사이즈는 112로 리스트로 변환했을 때보다 현저히 작은 값을 가진다.
이는 더 큰 리스트 일수록 더 값 차이가 커지게 된다. 이로써 큰 데이터를 처리할 때는 generator 로 메모리를 줄일 수 있다.
##### Generator 속도
def gen_case():
gen_ex = (n*n for n in range(500))
for v in gen_ex:
pass
def general_case():
list_ex = [n*n for n in range(500)]
for v in list_ex:
pass
%timeit gen_case()
%timeit general_case()
#출력
# 45 µs ± 431 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# 43.6 µs ± 2.82 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
k) Function Arguments (asterisk를 위한 buildup)
- 함수에서 입력되는 arguments에는 다양한 형태가 있다.
k-i) keyword : 함수에서 입력되는 parameter의 직접 변수명을 사용한다.
k-ii) default : 함수에서 입력되는 parameter의 기본값을 사용한다.
-> 즉, parameter를 입력하지 않을 경우 기본값을 출력한다.
##### Keyword Arguments Ex
def print_something(my_name, your_name):
print('hello {0}, My name is {1}'.format(your_name, my_name))
print_something(your_name = 'Tstory',my_name = 'emilia')
print_something('emilia', your_name = 'TEAMLAB')
#출력
# hello Tstory, My name is emilia
# hello Tstory, My name is emilia
한 파라미터가 keyword argument 쓰는 순간 뒤에도 다 keyword argument 사용해야한다.
순서가 맞으면 상관은 없지만 순서가 뒤바뀌었다면 keyword는 다 써줘야한다.
##### Default Argument Ex
def print_something(my_name, your_name="Tstory"):
print('hello {0}, My name is {1}'.format(your_name, my_name))
print_something('emilia')
#출력
# hello Tstory, My name is emilia
l) Asterisk (가변인자, *args)
- 개수가 정해지지 않은 변수를 함수의 parameter로 사용한다.
- keyword arguments 와 함께 argument 추가가 가능하다.
- asterisk (*) 기호를 사용하여 함수의 파라미터를 표시한다.
- 입력된 값은 tuple type이다.
- 오직 한 개만, 맨 마지막 paameter 위치에 사용이 가능하다.
* keyword asterisk (키워드 가변인자, **kwarg)
- 파라미터 이름을 따로 지정하지 않고 입력한다.
- dictionary type을 사용한다.
- 기존 가변인자 다음에 활용한다.
* Asterisk Unpacking
- tuple, dictionary 등 자료형의 값을 unpacking 한다.
- 함수의 입력값, zip 등에 유용하게 사용된다.
##### Asterisk Ex
def asterisk_test( *args):
x,y,z = args
return x,y,z
print(asterisk_test(1,2,3)) #3개 값 필요. 2,4개 입력시 에러.
#출력
# (1,2,3)
##### Keyword Asterisk Ex
def kwargs_test_1(**kwargs):
print(kwargs)
kwargs_test_1(first = 3, second=5, third = 5)
#출력
# {'first': 3, 'second': 5, 'third': 5}
def kwargs_test_3(one, two, *args, **kwargs):
print(args)
print(one+two+sum(args))
print(kwargs)
kwargs_test_3(3,4,5,6,7,8,9, first = 3, second=4, third = 5) #args = (5,6,7,8,9)
kwargs_test_3(3, two =10, first = 3, second=4, third = 5) #no args
#출력
(5, 6, 7, 8, 9)
42
{'first': 3, 'second': 4, 'third': 5}
()
13
{'first': 3, 'second': 4, 'third': 5}
##### Asterisk Unpacking Ex
def asterisk_test(a,args):
print(a,args)
print(type(args))
asterisk_test(1,(2,3,4,5,6)) #arg는 튜플이여서 이 자체로 하나의 변수이므로 에러x
#출력
# 1 (2, 3, 4, 5, 6)
# <class 'tuple'>
asterisk_test(1,*(2,3,4,5,6)) #arg 를 unpacking 하면서 여러 값들로 입력이 되기에 에러 발생
#에러발생
##### Asterisk Unpacking Ex
a,b,c = ([1,2],[3,4],[5,6])
print(a,b,c)
data = ([1,2],[3,4],[5,6])
print(*data)
#출력
# [1, 2] [3, 4] [5, 6]
# [1, 2] [3, 4] [5, 6]
##### Keyword Asterisk Unpacking
def asterisk_test(a,b,c,d):
print(a,b,c,d)
data = {"b":1, "c":2, "d":3}
asterisk_test(10,**data)
#출력
# 10 1 2 3
def asterisk_test(a,b,c,d,e=0):
print(a,b,c,d,e)
data = {"d":1, "c":2, "b":3, 'e':56}
asterisk_test(10,b=3,c=3,d=1,e=56)
asterisk_test(10,**data)
#출력
# 10 3 3 1 56
# 10 3 2 1 56
##### Asterisk with zip
#Asterisk X
ex = ([1,2],[3,4],[5,6])
a,b,c = ex
for data in zip(a,b,c):
print(sum(data))
#출력
# 9
# 12
#Asterisk O
ex = ([1,2],[3,4],[5,6],[5,6],[5,6])
for data in zip(*ex):
print(data)
#출력
# (1, 3, 5, 5, 5)
# (2, 4, 6, 6, 6)
Pythonic Code의 주요 기법은 끝!
Step3에서는 pythonic code를 활용한 linear algebra 에 대해서 정리를 해보려 한다.
끗!
'Python > Pythonic Code' 카테고리의 다른 글
Pythonic Code #3 (Linear Algebra_vector and matrix) (0) | 2023.04.03 |
---|---|
Pythonic Code #1 (split, join, list comprehension, enumerate, zip) (0) | 2023.04.02 |