티스토리 뷰

1. Json

- 왜 사용할까? 웹 환경에서 데이터를 주고 받는 가장 표준적인 방식이기 때문에

- 키를 이용해 원하는 데이터만 빠르게 추출할 수 있다

- 데이터가 쉽게 오염되지 않는다 => 데이터의 구조가 명확하고 규칙이 엄격하기 때문!

- 다른 포맷에 비해 용량이 조금 크다

 

1) JSON과 딕셔너리 변환(*s가 있으면 문자열 다루기)

- JSON 문자열을 파이썬 객체(딕셔너리 등)로 : json.loads(JSON문자열)

- 파이썬 객체를(딕셔너리를) JSON 문자열로: json.dumps(파이썬객체)

 

2) 파일 다루기

- JSON 파일을 읽어 파이썬객체로(딕셔너리 등): json.load(JSON파일) => python 객체가 됨

- 파이썬객체를(딕셔너리 등) JSON 파일에 쓰기: json.dump(파이썬객체를, JSON파일로)

 

2. 집합

- 중복이 없고, 순서가 없다!

 

1) 원소 추가/삭제

- 1개만 추가: add()

- 리스트나 문자열 원소 추가: update()

- 존재하는 값이 있을때만 제거: remove(존재하지 않는걸 제거하려면 오류 발생)

- discard: 존재하지 않는 원소를 제거하려고 하면 조용히 무시됨

 

2) 교집합, 차집합, 합집합

- 합집합 : |

- 교집합 : &

- 차집합 : -

 

3. CSV

- 같은 데이터라면 json파일보다 용량을 적게 소모한다

- 하지만 데이터 오염에 취약하다(예: 쌍따옴표 처리 안함 등)

 

4. assert(조건식)

- 식이 참이면 통과, 거짓이면 AssertionError 에러 발생

assert(1==2) # AssertionError

 

5. 클로저

- 외부 함수의 변수값을 내부 함수가 기억해서 쓸 수 있게 만드는 함수

* 재귀함수는 자기자신을 다시 호출함

- 왜 쓸까?

1) 설정값 기억: 설정 값을 기억하는 함수 만들기(특정 동작을 하는 함수 재사용 가능)

def adder(n): # n을 기억하는 함수를 만들어주는 공장
    def helper(x): # X+n을 계산하는 실제 함수
        return x + n
    return helper # 재귀함수라면 helper가아니라 adder를 반환해야함
    
    
add_three = adder(3)
print(add_three) # <function adder.<locals>.helper at 0x7fdd7fe6a840>
print(add_three(6)) # 9

2) 변수를 감추고 싶을 때 (은닉화)

def counter():
    count = 0 # count는 지역변수여서 외부에서는 count에 바로 접근 못함
    def inc(): # 오직 inc()를 통해서만 count 조작 가능
        nonlocal count
        count += 1
        return count
    return inc

a = counter()
print(a) # <function counter.<locals>.inc at 0x7fdd7fea7a60>
# a는 inc()함수다
print(a()) # 1
 
# print(a.count) # error

 

3) 데코레이터

def decorator(func):
    def wrapper():
        print("Before")
        func()
        print("After")
    return wrapper

 

- 동작원리

[adder(3)]
│
├─ [n = 3] ← 여기 저장됨 (사라지지 않음!)
│
└─ returns ➝ helper(x) ← 이 함수가 add_three가 됨
                     (x + 기억된 n 값을 계산)

 

6. filter(조건, 리스트) : 조건에 맞는 값만 반환(반환 타입은 filter) 

data = [i for i in range(10) if i<5]
print(data) # [0, 1, 2, 3, 4]

data2 = list(map(lambda x: x<5, range(10))) # 값을 변환
print(data2) # [True, True, True, True, True, False, False, False, False, False]

data3 = list(filter(lambda x: x<5, range(10))) # 값을 조건에 따라 거르기
print(data3) # [0, 1, 2, 3, 4]

 

7. 리스트컴프리헨션과 map의 차이점

* map: 데이터 구조의 각 원소들에 동일한 함수를 적용해 새로운 데이터를 만드는 함수

- 리스트컴프리헨션: 바로 계산해서 리스트로 만듦 => 메모리에 한꺼번에 저장 => 빠르게 값 계산하고 바로 쓰고 싶을 때

- map은 데이터를 map이라는 클래스로 저장하고, 데이터가 필요해 질 때 주어진 연산을 수행 => 지연 평가

=> 메모리 아끼고, 필요한 순간에만 계산하고 싶을 때

data = map(lambda x: x * 2, range(5))
print(data)  # <map object at 0x...> # 그냥 준비만
print(list(data))  # [0, 2, 4, 6, 8] # 필요할 때 계산

* 참고

- map, filter, 제너레이터(yield): 지연평가

- 리스트컴프리헨션: 즉시평가

** filter: 선택만, map: 변환만 => 리스트컴프리헨션: 한번에 가능

 

8. 지연 평가

- list(map(...))을 할 경우 전부 메모리에 올라가서 폭발! =>map인 채로 사용해 필요한것만 보고 끝낼 수 있음

# 10억 개짜리 데이터
nums = map(int, open("huge_file.txt"))

for x in nums:
    if x > 1000000:
        break  # 필요한 것만 보고 끝낼 수 있음!

 

9. itemgetter(): 리스트나 튜플, 딕셔너리 등에서 n번째 요소 또는 특정 키에 해당하는 값을 꺼내는 함수

- lambda x:x[1] 대신 itemgetther(1)을 쓰면 더 짧고 빠르고 명확함, 내부적으로 c로 구현되어 있어 lambda보다 성능이 좋다

* python도 C로 만들어졌지만, lambda는 파이썬 인터프리터가 한 줄씩 해석, itemgetter는 이미 C로 구현된 함수라 인터프리터 거치지 않고 바로 실행됨

from operator import itemgetter

students = [
    ("Alice", 90),
    ("Bob", 85),
    ("Charlie", 95)
]

sorted(students, key=itemgetter(0))
# [('Alice', 90), ('Bob', 85), ('Charlie', 95)]

sorted(students, key=itemgetter(1))
# [('Bob', 85), ('Alice', 90), ('Charlie', 95)]

- 시간 비교

from operator import itemgetter
import time

data = [(i, i+1) for i in range(100000)]

# lambda
start = time.time()
sorted(data, key=lambda x: x[1])
print("lambda:", time.time() - start)

# itemgetter
start = time.time()
sorted(data, key=itemgetter(1))
print("itemgetter:", time.time() - start)

# lambda: 0.011322498321533203
# itemgetter: 0.006901264190673828
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/02   »
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
글 보관함