<jupyter_start><jupyter_text>1. Pythonic Code- 파이썬 스타일의 코딩 기법- 파이썬 특유의 문법을 활용하여 효율적으로 코드를 표현함- 고급 코드를 작성할 수록 더 많이 필요해짐- **Split & Join**- **List Comprehension**- **Enumerate & Zip** Why Pythonic Code?- **남 코드에 대한 이해도**많은 개발자들이 python 스타일로 코딩한다- **효율**단순 for loop append보다 list가 조금 더 빠르다익숙해지면 코드도 짧아진다.- **간지**쓰면 왠지 코드 잘 짜는 거처럼 보인다  일반적인 code와 Pythonic code 비교<jupyter_code># 일반 코드

colors = ["a", "b", "c", "d", "e"]
result = ""

for s in colors:
    result += s

print(result)
# pythonic code

colors = ["red", "blue", "green", "yellow"]
result = "".join(colors)

print(result)<jupyter_output>redbluegreenyellow<jupyter_text>Split & Join  Split- String Type의 값을 나눠서 List 형태로 변환<jupyter_code>items = 'zero one two three'.split() # 빈칸을 기준으로 문자열 나누기
items
example = 'python,jquery,javascript' # ","을 기준으로 문자열 나누기
example.split(",")
# 리스트에 있는 각 값을 a,b,c 변수로 unpacking
a, b, c = example.split(",")
print(a)
print(b)
print(c)
example = 'cs50.gachon.edu'
# "."을 기준으로 문자열 나누기 → Unpacking
subdomain, domain, tld = example.split('.')
print(subdomain)
print(domain)
print(tld)<jupyter_output>cs50
gachon
edu<jupyter_text>Join- String List를 합쳐 하나의 String으로 반환할 때 사용<jupyter_code>colors = ['red', 'blue', 'green', 'yellow']
result = ''.join(colors)
result
result = ' '.join(colors) # 연결 시 빈칸 1칸으로 연결
result
result = ', '.join(colors) # 연결 시 ", "으로 연결
result
result = '-'.join(colors) # 연결 시 "-"으로 연결
result<jupyter_output><empty_output><jupyter_text>List Comprehensions- 기존 List 사용하여 간단히 다른 List를 만드는 기법- 포괄적인 List, 포함되는 리스트라는 의미로 사용됨- 파이썬에서 가장 많이 사용되는 기법 중 하나- 일반적으로 for + append 보다 속도가 빠름<jupyter_code># general style
result = []
for i in range(10):
    result.append(i)
result
# list comprehension
result = [i for i in range(10)]
result
# list comprehesnion with filter
result = [i for i in range(10) if i % 2 == 0]
result
# Nested For loop
word_1 = "Hello"
word_2 = "World"

result = [i+j for i in word_1 for j in word_2]
result
case_1 = ["A","B","C"]
case_2 = ["D","E","A"]
result = [i+j for i in case_1 for j in case_2]
result
result = [i+j for i in case_1 for j in case_2 if not(i==j)]
# Filter: i랑 j과 같다면 List에 추가하지 않음
print(result)
result.sort()
print(result)
words = 'The quick brown fox jumps over the lazy dog'.split()
# 문장을 빈칸 기준으로 나눠 list로 변환
print(words)

# Nested List Comprehension
stuff = [[w.upper(), w.lower(), len(w)] for w in words]
# list의 각 elemente들을 대문자, 소문자, 길이로 변환하여 two dimensional list로 변환
for i in stuff:
    print(i)
# Two dimensional VS One dimensional
case_1 = ["A","B","C"]
case_2 = ["D","E","A"]
result = [i+j for i in case_1 for j in case_2]
result
result = [ [i+j for i in case_1] for j in case_2]
result<jupyter_output><empty_output><jupyter_text>Enumerate & Zip  Enumerate- List의 element를 추출할 때 번호를 붙여서 추출<jupyter_code>for i, v in enumerate(['tic', 'tac', 'toe']):
    # list의 있는 index와 값을 unpacking
    print(i, v)
# enumerate한 값의 형태는 tuple
mylist = ["a","b","c","d"]
list(enumerate(mylist)) # list의 있는 index와 값을 unpacking하여 list로 저장
# 문장을 list로 만들고 list의 index와 값을 unpacking하여 dict로 저장
{i:j for i,j in enumerate('Gachon University is an academic institute located in South Korea.'.split())}<jupyter_output><empty_output><jupyter_text>Zip- 두 개의 list의 값을 병렬적으로 추출함<jupyter_code>alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3']
for a, b in zip(alist, blist): # 병렬적으로 값을 추출
    print(a,b)
a, b, c = zip((1,2,3), (10,20,30), (100,200,300)) #각 tuple의 같은 index끼리 묶음

# 각 Tuple 같은 index를 묶어 합을 list로 변환
[sum(x) for x in zip((1,2,3), (10,20,30), (100,200,300))]
alist = ['a1', 'a2', 'a3']
blist = ['b1', 'b2', 'b3']

for i, (a, b) in enumerate(zip(alist, blist)):
    print(i, a, b) # index alist[index] blist[index] 표시<jupyter_output>0 a1 b1
1 a2 b2
2 a3 b3<jupyter_text>Lambda & MapReduce  Lambda- 함수 이름 없이, 함수처럼 쓸 수 있는 익명함수- 수학의 람다 대수에서 유래함- Python 3부터는 권장하지는 않으나 여전히 많이 쓰임<jupyter_code># general function
def f(x, y):
    return x + y
print(f(1, 4))

# lambda function
f = lambda x, y: x + y
print(f(1, 4))
f = lambda x: x ** 2
print(f(3))

f = lambda x: x / 2
print(f(3))

print((lambda x: x + 1)(5)) # 만듬과 동시에 함수 적용 가능<jupyter_output>9
1.5
6<jupyter_text>Map & Reduce- Lambda, map, reduce는 간단한 코드로 다양한 기능을 제공- 그러나 코드의 직관성이 떨어져서 lambda나 reduce는 python3에서 사용을 권장하지 않음- Legacy library나 다양한 머신러닝 코드에서 여전히 사용중  Map function- Sequence 자료형 각 element에 동일한 function을 적용함- 두 개 이상의 list에도 적용 가능함, if filter도 사용가능- python3는 iteration을 생성 -> list을 붙여줘야 list 사용가능- 실행시점의 값을 생성, 메모리 효율적<jupyter_code># Map

def f(x, y):
    return x + y
print(f(1, 4))

f = lambda x, y: x+y
print(f(1, 4))
ex = [1, 2, 3, 4, 5]
f = lambda x: x ** 2
print(list(map(f, ex)))
ex = [1, 2, 3, 4, 5]
f = lambda x, y: x + y
print(list(map(f, ex, ex)))

list(map(
    lambda x: x ** 2 if x % 2 == 0 else x, # x가 2의배수이면 제곱, 아니면 원래 값
    ex))
# python 3에는 list를 꼭 붙여줘야함
ex = [1,2,3,4,5]
print(list(map(lambda x: x+x, ex)))
print((map(lambda x: x+x, ex)))
# map의 각 원소를 뽑기 위해서는 for문 이용
f = lambda x: x ** 2
print(map(f, ex))
for i in map(f, ex):
    print(i)
result = map(f, ex)
print(result)
print(next(result))
# sys.getsizeof() : 객체의 메모리 사이즈를 바이트 단위로 반환
import sys
print( sys.getsizeof(ex) ) # [1, 2, 3, 4, 5]의 메모리 사이즈
print( sys.getsizeof(map(lambda x: x+x, ex)) ) # <map at 0x1972de12400>의 메모리 사이즈
print( sys.getsizeof(list(map(lambda x: x+x, ex))) ) # [2, 4, 6, 8, 10]의 메모리 사이즈

# list보다 map의 메모리가 더 작음!!<jupyter_output>104
56
128<jupyter_text>Reduce function- map function과 달리 list에 똑같은 함수를 적용해서 통합<jupyter_code># Reduce
from functools import reduce
print( reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) ) # 리스트의 각 원소를 순서대로 적용시킴
# Reduce function의 Example(factorial)
def factorial(n):
    return reduce(
            lambda x, y: x*y, range(1, n+1))

factorial(5)<jupyter_output><empty_output><jupyter_text>Asterisk- 흔히 알고 있는 * 를 의미함- 단순 곱셈, 제곱연산, **가변 인자** 활용 등 다양하게 사용됨<jupyter_code># *args: 첫 argument를 제외한 나머지를 한 번에 받음(tuple 형태)
def asterisk_test(a, *args):
    print(a, args)
    print(type(args))
    
asterisk_test(1,2,3,4,5,6)
# **kargs: 첫 argument를 제외한 나머지를 한 번 에 받음(dict 형태)
def asterisk_test(a, **kargs):
    print(a, kargs)
    print(type(kargs))
    
asterisk_test(1, b=2, c=3, d=4, e=5, f=6) # key와 value로 지정한 겨우!!<jupyter_output>1 {'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
<class 'dict'><jupyter_text>Asterisk – unpacking a container- tuple, dict 등 자료형에 들어가 있는 값을 unpacking- 함수의 입력값, zip 등에 유용하게 사용가능> **unpacking**이란?> - 배열로 묶여있는 값들을 풀어버리는 것> - ex) [1,2,3,4,5] 를 unpacking => 1,2,3,4,5<jupyter_code># unpacking한 값을 받아와서 다시 tuple 형태로 묶음!!
def asterisk_test(a, *args):
    print(a, args)
    print(type(args))
    
asterisk_test(1, *(2,3,4,5,6))
asterisk_test(1, (2,3,4,5,6))  # unpacking하지 않을 경우 (2,3,4,5,6)이 하나의 argument로 적용, two dimensional tuple이 됨
def asterisk_test(a, args):
    print(a, *args)  # 그대로 들어온 argument인 (2,3,4,5,6)을 unpacking
    print(type(args))
    
asterisk_test(1, (2,3,4,5,6))
# asterisk를 사용하여 간단히 unpacking
a, b, c = ([1, 2], [3, 4], [5, 6])
print(a, b, c)

data = ([1, 2], [3, 4], [5, 6])
print(*data)
def asterisk_test(a, b, c, d):
    print(a, b, c, d)

data = {"b":1 , "c":2, "d":3}
asterisk_test(10, **data)
for data in zip(*([1, 2], [3, 4], [5, 6])):
    print(data)<jupyter_output>(1, 3, 5)
(2, 4, 6)<jupyter_text>Linear algebra codes Vector<jupyter_code>vector_a = [1, 2, 10] # List로 표현했을 경우
vector_b= (1, 2, 10) # Tuple로 표현했을 경우
vector_c = {'x': 1, 'y': 1, 'z': 10} # dict 표현했을 경우

print(vector_a, vector_b, vector_c) 
u = [2, 2]
v = [2, 3]
z = [3, 5]

result = [t for t in zip(u, v, z)]
print (result)
# Vector의 연산
u = [1, 2, 3]
v = [4, 4, 4]
alpha = 2
result = [2*sum(t) for t in zip(u, v)]
print(result)<jupyter_output>[10, 12, 14]<jupyter_text>Matrix<jupyter_code># matrix의 합
matrix_a = [[3, 6], [4, 5]]
matrix_b = [[5, 8], [6, 7]]
result = [[sum(row) for row in zip(*t)]
          for t in zip(matrix_a, matrix_b)]

print(result)
# matrix의 scalar곱
matrix_a = [[3, 6], [4, 5]]
alpha = 4
result = [[alpha * element for element in t] for t in matrix_a]

print(result)
# transpose
matrix_a = [[1, 2, 3], [4, 5, 6]]
result = [[element for element in t] for t in zip(*matrix_a)]

print( [t for t in zip(*matrix_a)] )
print(result)
# matrix multiplication
matrix_a = [[1, 1, 2], [2, 1, 1]]
matrix_b = [[1, 1], [2, 1], [1, 3]]
result = [[sum(a * b for a, b in zip(row_a, column_b))
          for column_b in zip(*matrix_b)] for row_a in matrix_a]
print(result)<jupyter_output>[[5, 8], [5, 6]]
{'fraction_non_alphanumeric': 0.16636636636636637, 'fraction_numerical': 0.03831831831831832, 'mean_word_length': 4.236477987421384, 'pattern_counts': {'":': 3, '<': 46, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '518280', 'license': 'MIT', 'n_tokens_mistral': 4533, 'n_tokens_neox': 4898, 'n_words': 1189, 'path': 'Python/ML_basic/1.Pythonic Code/1-1.Pythonic Code.ipynb', 'repo_name': 'statKim/TIL', 'size': '8325'}