pythonic code

Pythonic code


  • 파이썬 스타이의 코딩 기법
  • 파이썬 특유의 문법을 활용하여 효율적으로 코드를 표현함
  • 고급 코드를 작성 할 수록 더 많이 필요해짐

split & join

split 함수

In [1]:
items ='zero one two three'.split()  # 빈칸을 기준으로 문자열 나누기
print(items)
['zero', 'one', 'two', 'three']
In [2]:
example ='python,java,javascript'# ","을 기준으로 문자열 나누기
example.split(',')
Out[2]:
['python', 'java', 'javascript']
In [3]:
a,b,c=example.split(',')   # 리스트에 있는 각 값을 a,b,c 변수로 unpacking
print(a,b,c)
python java javascript
In [4]:
example ='teamlab.technology.io'
subdomain, domain, tld=example.split('.')
print(subdomain, domain, tld)
teamlab technology io
  • String type의 값을 '구분자'로 나눠서 List형태로 변환


join 함수

In [5]:
colors =['red','blue','green','yellow']
result =''.join(colors)
result
Out[5]:
'redbluegreenyellow'
In [6]:
result =' '.join(colors)  # 연결시 빈칸 1칸으로 연결
result
Out[6]:
'red blue green yellow'
In [7]:
result =', '.join(colors)   # 연결시", "으로연결
result
Out[7]:
'red, blue, green, yellow'
In [8]:
result ='-'.join(colors)  # 연결시"-"으로연결
result
Out[8]:
'red-blue-green-yellow'
  • String으로 구성된 list를 합쳐서 하나의 string으로 반환


List Comprehension

  • 기존 List사용하여 간단히 다른 List를 만드는 기법
  • 일반적으로 for+ append 보다 속도가 빠름
In [9]:
# General Style
result =[]
for i in range(10):
    result.append(i)
result
Out[9]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [10]:
# List Comprehension
result =[i for i in range(10)]
print(result)

result =[i for i in range(10) if i%2==0]
print(result)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]
In [11]:
# Nested For loop
word_1 ="Hello"
word_2 ="World"
result =[i+j for i in word_1 for j in word_2]
print(result)
['HW', 'Ho', 'Hr', 'Hl', 'Hd', 'eW', 'eo', 'er', 'el', 'ed', 'lW', 'lo', 'lr', 'll', 'ld', 'lW', 'lo', 'lr', 'll', 'ld', 'oW', 'oo', 'or', 'ol', 'od']
In [12]:
case_1 =["A","B","C"]
case_2 =["D","E","A"]
result =[i+j for i in case_1 for j in case_2]
result
Out[12]:
['AD', 'AE', 'AA', 'BD', 'BE', 'BA', 'CD', 'CE', 'CA']
In [13]:
# Filter: i랑j과같다면List에추가하지않음
# [i+jif not(i==j) else i for i in case_1 for j in case_2]
result =[i+j for i in case_1 for j in case_2 if not(i==j)]
result
Out[13]:
['AD', 'AE', 'BD', 'BE', 'BA', 'CD', 'CE', 'CA']
In [14]:
result.sort()
result
Out[14]:
['AD', 'AE', 'BA', 'BD', 'BE', 'CA', 'CD', 'CE']
  • 조건문을 넣어서 만들 수 있음.
In [15]:
# 문장을 빈칸 기준으로 나눠 list로 변환
words ='The quick brown fox jumps over the lazy dog'.split()
print(words)
['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
In [16]:
# list의 각 elemente들을 대문자, 소문자, 길이로 변환하여 two dimensional list로변환
stuff=[[w.upper(),w.lower(),len(w)] for w in words]
print(stuff)
[['THE', 'the', 3], ['QUICK', 'quick', 5], ['BROWN', 'brown', 5], ['FOX', 'fox', 3], ['JUMPS', 'jumps', 5], ['OVER', 'over', 4], ['THE', 'the', 3], ['LAZY', 'lazy', 4], ['DOG', 'dog', 3]]
In [17]:
case_1 =["A","B","C"]
case_2 =["D","E","A"]
result =[i+j for i in case_1 for j in case_2]
result
Out[17]:
['AD', 'AE', 'AA', 'BD', 'BE', 'BA', 'CD', 'CE', 'CA']
In [18]:
result =[ [i+j for i in case_1] for j in case_2]
result
Out[18]:
[['AD', 'BD', 'CD'], ['AE', 'BE', 'CE'], ['AA', 'BA', 'CA']]
  • 여기서는 뒤에 있는 for j in case_2가 먼저 실행이 된다.

enumerate & zip

enumerate

  • list의 element를 추출할 때 번호를 붙여서 추출
In [19]:
# list에 있는 index와 값을 unpacking
for i,v in enumerate(['tic','tac','toe']):
    print(i,v)
0 tic
1 tac
2 toe
In [20]:
mylist=['a','b','c','d']
# list에 있는 index와 값을 unpacking하여 list로저장
list(enumerate(mylist))
Out[20]:
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
In [21]:
# 문장을 list로 만들고 list의 index와 값을 unpacking하여 dict로저장
{i:j for i,j in enumerate('Artificial intelligence (AI), is intelligence demonstrated by machines,\
                         unlike the natural intelligence displayed by humans and animals.'.split())}
Out[21]:
{0: 'Artificial',
 1: 'intelligence',
 2: '(AI),',
 3: 'is',
 4: 'intelligence',
 5: 'demonstrated',
 6: 'by',
 7: 'machines,',
 8: 'unlike',
 9: 'the',
 10: 'natural',
 11: 'intelligence',
 12: 'displayed',
 13: 'by',
 14: 'humans',
 15: 'and',
 16: 'animals.'}

zip

  • 두 개의 list의 값을 병렬적으로 추출
In [22]:
alist=['a1','a2','a3']
blist=['b1','b2','b3']
for a,b in zip(alist,blist):# 병렬적으로값을추출
    print(a,b)
a1 b1
a2 b2
a3 b3
In [23]:
[c for c in zip(alist,blist)]
Out[23]:
[('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]
In [24]:
a,b,c=zip((1,2,3),(10,20,30),(100,200,300))
print(a,b,c)
(1, 10, 100) (2, 20, 200) (3, 30, 300)
In [25]:
# 각Tuple 같은 index를 묶어 합을 list로변환
[sum(x) for x in zip((1,2,3),(10,20,30),(100,200,300))]
Out[25]:
[111, 222, 333]
In [26]:
alist=['a1','a2','a3']
blist=['b1','b2','b3']

# index alist[index] blist[index] 표시
for i,(a,b)in enumerate(zip(alist,blist)):
    print(i,a,b)
0 a1 b1
1 a2 b2
2 a3 b3

lambda & map &reduce

lambda

  • 함수 이름 없이, 함수처럼 쓸 수 있는 익명함수
  • 수학의 람다 대수에서 유래함
In [27]:
# general function
def f(x, y):
    return x +y
print(f(1,4))
5
In [28]:
# Lambda function
f=lambda x, y: x+y
print(f(1, 4))
5
In [29]:
(lambda x,y:x+y)(10,50)
Out[29]:
60
  • Python 3부터는 권장하지는 않으나 여전히 많이 쓰임


map

In [30]:
ex=[1,2,3,4,5]
f=lambda x,y: x+y

# 두개 이상 list
print(list(map(f, ex, ex)))

# filter
print(list(map(lambda x: x**2 if x % 2==0 else x, ex)))
[2, 4, 6, 8, 10]
[1, 4, 3, 16, 5]
  • 두개 이상의 list에도 적용 가능함, if filter도 사용가능
In [31]:
ex =[1,2,3,4,5]
print(list(map(lambda x: x+x, ex)))
print((map(lambda x: x+x, ex)))
[2, 4, 6, 8, 10]
<map object at 0x0000029CBDA15848>
In [32]:
f=lambda x: x**2
print(map(f, ex))
for i in map(f, ex):
    print(i)
<map object at 0x0000029CBDA15B48>
1
4
9
16
25
In [33]:
result =map(f, ex)
print(next(result))
1
  • python3는 iteration을생성 → list을 붙여줘야 list 사용가능
  • 실행시점의 값을 생성, 메모리 효율적
In [34]:
def f(x):
    return x+5
ex=[1,2,3,4,5]
list(map(f,ex))
print([f(value) for value in ex])
[6, 7, 8, 9, 10]
  • map대신 comprehesion을 이용하는걸 더 권장한다


reduce

image.png

In [35]:
from functools import reduce
print(reduce(lambda x,y:x+y,[1,2,3,4,5]))
15
  • map function과 달리 list에 똑같은 함수를 적용해서 통합

요약

Lambda, map, reduce는 간단한 코드로 다양한 기능을 제공 그러나 코드의 직관성이 떨어져서 lambdareducepython3에서 사용을 권장하지 않음. Legacy library나 다양한 머신러닝 코드에서 여전히 사용중


iterable object

  • Sequence형 자료형에서 데이터를 순서대로 추출하는 object
In [36]:
for city in["Seoul", "Busan", "Pohang"]:
    print(city, end="\t")
for language in("Python", "C", "Java"):
    print(language, end="\t")
for char in "Python is easy":
    print(char, end= " ")
Seoul	Busan	Pohang	Python	C	Java	P y t h o n   i s   e a s y 
In [37]:
cities = ["Seoul", "Busan", "Jeju"]
iter_obj= iter(cities)

print(next(iter_obj))
print(next(iter_obj))
print(next(iter_obj))
print(next(iter_obj))
Seoul
Busan
Jeju
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-37-66c7b3ba1e48> in <module>
      5 print(next(iter_obj))
      6 print(next(iter_obj))
----> 7 print(next(iter_obj))

StopIteration: 
  • 내부적 구현으로 __iter____next__ 가 사용됨
  • iter()next() 함수로 iterable 객체를 iterator object로 사용

generator

  • iterable object를 특수한 형태로 사용해주는 함수
  • element가 사용되는 시점에 값을 메모리에 반환
    : yield를 사용해 한번에 하나의 element만 반환함
In [38]:
# 일반적인 list
def general_list(value):
    result = []
    for i in range(value):
        result.append(i)
    return result
In [39]:
print(general_list(50))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
In [40]:
import sys
result=general_list(50)
sys.getsizeof(result)
Out[40]:
528
In [41]:
# Generator
def generator_list(value):
    result = []
    for i in range(value):
        yield i
In [42]:
generator_list(50)
Out[42]:
<generator object generator_list at 0x0000029CBDAF4148>
In [43]:
sys.getsizeof(generator_list(50))
Out[43]:
120
In [44]:
for a in generator_list(10):
    print(a,end=' ')
0 1 2 3 4 5 6 7 8 9 

generator 만들기

In [45]:
gen_ex= (n*n for n in range(500))
print(type(gen_ex))
<class 'generator'>
  • list comprehension과 유사한 형태로 generator형태의 list 생성
  • generator expression이라는 이름으로도 부름
  • [ ] 대신 ( )를 사용하여 표현
In [46]:
from sys import getsizeof
gen_ex= (n*n for n in range(500))
print(getsizeof(gen_ex))
print(getsizeof(list(gen_ex)))

list_ex= [n*n for n in range(500)]
print(getsizeof(list_ex))
120
4576
4272
  • 일반적인 iterator는 generator에 비해 훨씬 큰 메모리 용량 사용

요약

list 타입의 데이터를 반환해주는 함수는 generator로만들어라!
→ 읽기 쉬운 장점, 중간 과정에서 loop가 중단될 수 있을때!
큰 데이터를 처리할 때는 generator expression을고려하라!
→ 데이터가 커도 처리의 어려움이 없음
파일 데이터를 처리할 때도 generator를 쓰자


function passing arguments

Keyword arguments

In [47]:
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")
Hello TEAMLAB, My name is Sungchul
Hello TEAMLAB, My name is Sungchul
  • 함수에 입력되는 parameter의 변수명을 사용, arguments를 넘김

default arguments

In [48]:
def print_somthing_2(my_name,your_name="TEAMLAB"):
    print("Hello {0}, My name is {1}".format(your_name,my_name))
print_somthing_2("Sungchul","TEAMLAB")
print_somthing_2("Sungchul")
Hello TEAMLAB, My name is Sungchul
Hello TEAMLAB, My name is Sungchul
  • parameter의 기본값을 사용, 입력하지 않을 경우 기본값 출력


asterisk

가변인자

  • 개수가 정해지지 않은 변수를 함수의 parameter로 사용하는 법
  • Keyword arguments와 함께,argument추가가 가능
  • Asterisk(*) 기호를 사용하여 함수의 parameter를 표시함
  • 입력된 값은 tuple type으로 사용할 수 있음
  • 가변인자는 오직 한 개만 맨마지막 parameter 위치에 사용가능
In [49]:
def asterisk_test(a,b,*args):
    return a+b+sum(args)
print(asterisk_test(1,2,3,4,5))
15
In [50]:
def asterisk_test(a, *args):
    print(a, args)
    print(type(args))

asterisk_test(1,2,3,4,5,6)
1 (2, 3, 4, 5, 6)
<class 'tuple'>
In [51]:
def asterisk_test_2(*args):
    x,y,z =args
    return x,y,z
print(asterisk_test_2(3,4,5))
(3, 4, 5)
  • 가변인자는 일반적으로 *args를 변수명으로사용
  • 기존parameter 이후에 나오는 값을 tuple로 저장함


키워드 가변인자

  • Parameter 이름을 따로 지정하지 않고 입력하는 방법
  • asterisk(*) 두개를 사용하여 함수의 parameter를 표시함
  • 입력된 값은 dict type으로 사용할 수 있음
  • 가변인자는 오직 한 개만 기존 가변인자 다음에 사용
In [52]:
def kwargs_test_1(**kwargs):
    print(kwargs)
In [53]:
def asterisk_test(a, **kargs):
    print(a, kargs)
    print(type(kargs))

asterisk_test(1, b=2, c=3, d=4, e=5, f=6)
1 {'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
<class 'dict'>
In [54]:
def kwargs_test_3(one,two,*args,**kwargs):
    print(one+two+sum(args))
    print(kwargs)
kwargs_test_3(3,4,5,6,7,8,9,first=3,second=4,third=5)
42
{'first': 3, 'second': 4, 'third': 5}
  • dict형으로 저장된다.

unpaking container

In [55]:
def asterisk_test(a, *args):
    print(a, args)
    print(type(args))


asterisk_test(1, *(2, 3, 4, 5, 6))
1 (2, 3, 4, 5, 6)
<class 'tuple'>
In [56]:
def asterisk_test(a, args):
    print(a, *args)
    print(type(args))

asterisk_test(1, (2,3,4,5,6))
1 2 3 4 5 6
<class 'tuple'>
  • tuple, dict 등 자료형에 들어가 있는 값을 unpacking
  • 함수의 입력값, zip 등에 유용하게 사용가능
In [57]:
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]
In [58]:
def asterisk_test(a, b, c, d, e=0):
    print(a, b, c, d, e)


data = {"d":1 , "c":2, "b":3}
asterisk_test(10, **data)
10 3 2 1 0
  • **는 dict타입을 풀어줄때 사용한다.
In [59]:
for data in zip(*([1, 2], [3, 4], [5, 6])):
    print(data)
(1, 3, 5)
(2, 4, 6)

'AI > 이론' 카테고리의 다른 글

Numpy part II  (0) 2021.01.25
Numpy part I  (0) 2021.01.25
Python data handling  (0) 2021.01.22
File & Exception & Log Handling  (0) 2021.01.22
Module and Project  (0) 2021.01.21
Python Object Oriented Programming  (0) 2021.01.21
python data structure  (0) 2021.01.20
Variable & List  (0) 2021.01.19

+ Recent posts