728x90
반응형

📂 레퍼런스 카운트와 가비지 컬렉션
- 레퍼런스 카운트 : 객체를 참조하는 변수의 수
- 가비지 컬렉션 : 메모리 공간에 변수 등의 소멸 규칙 및 과정
- ➡ 레퍼런스 카운트가 0이 되면 가비지 컬렉션 대상
r1 = [1, 2, 3] # 리스트의 레퍼런스 카운트 = 1
r2 = r1 # 리스트의 레퍼런스 카운트 = 2
r1 = "python" # 리스트의 레퍼런스 카운트 = 1
r2 = "easy" # 리스트의 레퍼런스 카운트 = 0 (가비지 컬렉션 대상)
📁 객체
1. 수정 가능한/불가능한 객체
- mutable 객체 : 객체의 값 수정 가능 (리스트, 딕셔너리)
- immutable 객체 : 객체의 값 수정 불가능 (튜플, 문자열)
2. 얕은 복사 / 깊은 복사
- 객체 비교시 사용하는 연산자
(1) a == b # 변수 a와 b가 참조하는 객체의 내용이 같은가?
(2) a is b # 변수 a와 b가 참조하는 객체는 동일 객체인가? - 얕은 복사 : 파이썬이 복사하는 기본 방식
- ➡ mutable 객체시 문제 발생 (b[2][1] += 1의 경우 a도 변경됨)
a = ['python', ('easy', 'programming'), [123, 456] ]
b = list(a) # 얕은 복사
- 깊은 복사 : 복사 대상을 하나 더 생성
- ➡ 튜플, 문자열의 경우는 얕은 복사됨
import copy # deepcopy 함수 호출 위해
b = copy.deepcopy(a)
3. Iterator 객체 / Iterable 객체
- iter 함수 : 리스트에서 값을 꺼내는 기능의 'iterator 객체'를 생성/반환
a = [1, 2, 3, 4]
b = iter(a) # 변수 b에 iterator 객체 저장(참조)
next(b) # 1 (첫 번째 값 반환)
next(b) # 2 (두 번째 값 반환)
- iterator 객체 : iter 함수가 반환하는 객체
- iterable 객체 : iterator 객체를 얻을 수 있는 객체 (ex. 리스트, 튜플, 문자열 객체)
- ➡ iterable 객체는 iterator 객체를 생성할 수 있음
➡ iterable 객체를 대상으로 iter 함수를 호출해서 iterator 객체를 만듦 - for 루프 내부 동작 형태
for i in [1, 2, 3]: == ir = iter([1, 2, 3])
print(i, end=" ") while True:
try:
i = next(ir)
print(i, end=" ")
except StopIteration: # 꺼낼 것이 없으면
break
➡ for 루프의 반복 대상 = (iter 함수의 인자로 전달이 가능한) iterable 객체 / iterator 객체
📁 함수
1. 객체처럼 다뤄지는 함수/람다
- 람다 함수 : 이름 없는 함수 정의
lambda [매개변수 선언] : [표현식]
2. map & filterdef show(a, b): == ref = lambda a, b : a + b return a + b ref = (3, 4) ref = show(3, 4) - ➡ 람다 함수 : 이름 없는 함수 정의
➡ 매개변수 : 없을 경우 생략 가능
➡ 표현식 : 함수 호출 가능 - map 함수 : 저장된 값을 하나씩 전달하며 함수 호출
map ( [함수], [iterable 객체] ) - ➡ iterable객체 : 리스트, 튜플, 문자열
➡ 함수 매개변수가 2개 이상일 경우도 가능 - filter 함수 : 값을 걸러내는 기능
filter ( [True/False 반환 함수], [iterable 객체])
# map : 10이하 자연수 제곱
st = list(range(1, 11))
fst = list(map(lambda n: n**2, st))
# filter : 10이하 자연수 중에서 3의 배수
st = list(range(1, 11))
fst = list(filter(not(n%3), st))
# map & filter : 10이하 자연수의 제곱 중에서 3의 배수 고르기
st = list(range(1, 11))
fst = list(filter(lambda n: not(n%3), map(lambda n: n**2, st)))
3. 제너레이터 함수
- 제너레이터 함수 : yeild 순서에 맞게 값 return
def func():
print("first")
yield 1 # 첫 번째 호출시
print("second")
yield 2 # 두 번째 호출시
gen = func() # 제너레이터 객체 생성
next(gen) # gen = "first"
next(gen) # gen = "second"
- 제너레이터 특징
# 1부터 10까지 제곱
n = list(range(1, 11))
def pow(): == def pow():
for i in n: r = []
yield i ** 2 for i in n:
r.append(i ** 2)
== yield from n ** 2 return r
(yield from = for문 생략 가능)
➡ 리스트 길이에 상관 없이 메모리 크기 동일 (반환할 값을 미리 만들어서 저장X)
➡ map, filter 도 제너레이터 종류
4. 제너레이터 표현식
# 1부터 10까지 제곱
generator = (i**2 for i in range(1, 10)) # next() 통해 호출
comprehension = [i**2 for i in range(1, 10)] # 리스트에 저장
5. 함수 호출과 매개변수 선언에 있어서 *와 **의 사용 규칙
- 객체 전달 과정
- func(*iterable) : 리스트, 튜플, 문자열, 딕셔너리 키 풀어서 전달
- func(**dict) : 딕셔너리 값을 풀어서 전달
- 함수 정의 과정
- def func(*args) : 값을 튜플로 묶어서 args 전달
- def func(**args) : 값을 딕셔너리로 묶어서 args 전달
def func(*args1, **args2):
print(args1) # args1 = 튜플
print(args2) # args2 = 딕셔너리
func(1, a = 1) # (1) {'a' = 1}
func(2, 3, b = 2, c = 3) # (2, 3) {'b' = 2, 'c' = 3}
📁 리스트
1. 리스트 컴프리헨션
- 리스트 컴프리헨션 : for문 대신 리스트 생성 방식
a = [] == [x for x in rage(10)]
for i in range(10):
a.append(i)
- 조건 필터 추가 (조건 : i가 홀수인 경우)
a = [] == [i for i in range(10) if i % 2]
for i in range(10):
if i % 2:
a.append(i)
- 중첩된 for 루프 형태
a = [] == [i+j for i in range(10) for j in range(10)]
for i in range(10):
for j in range(10):
a.append(i+j)
2. map, filter 함수 대신하는 리스트 컴프리헨션
- map ➡ 리스트 컴프리헨션
st = list(range(1, 11))
fst = [n**2 for n in st]
- filter ➡ 리스트 컴프리헨션
st = list(range(1, 11))
fst = [n for n in st if not(n % 3)]
- map & filter ➡ 리스트 컴프리헨션
st = list(range(1, 11))
fst = [n**2 for n in st if (n**2) % 3 == 0]
3. 정렬 기술
- sort 메소드 : 리스트 자체를 수정 (리스트만 가능)
- 오름차순 정렬 : sort()
- 내림차순 정렬 : sort(reverse = True)
- key값 기준 정렬 : sort(key = 변수) / sort(key = lambda t : t[1])
- 문자열 길이 기준 정렬 : sort(key = len)
- sorted 메소드 : 정렬된 사본 생성 (튜플 등 iterable 객체 가능)
- 오름차순 정렬 : sorted(리스트)
📂 튜플
1. 튜플의 패킹과 언패킹
- 튜플 패킹 : 튜플로 값을 묶기
- 튜플 언패킹 : 튜플로 묶여 있는 값을 풀기
n = (1, 2, 3, 4, 5) # 튜플 패킹
n1, n2, *other = n # 튜플 언패킹
def func(n1, n2, *other):
print(n1, n2, other)
func(1, 2, 3, 4, 5) # 1, 2, (3, 4, 5)
2. 네임드 튜플
- 네임드 튜플 : 일반 튜플과 달리 위치별로 이름을 가짐 (튜플이라 변경 불가)
from collections import namedtuple
Tri = namedtuple('Triangle', ['bottom','height']) # 네임드 튜플 클래스'Triangle' 생성
t = Tri(3, 7)
print(t.bottom, t.height) # 3, 7
print(t[0], t[1]) # 3, 7
📂 딕셔너리
1. dict의 생성과 zip
- 딕셔너리 생성
d = {'a':1, 'b':2, 'c':3}
d = dict( [('a',1), ('b',2), ('c',3)] )
d = dict( a=1, b=2, c=3 ) # 키가 문자열인 경우
d = dict( zip(['a','b','c'], [1, 2, 3]) ) # zip함수 이용 (키, 값끼리 리스트에 묶어서 생성)
- 딕셔너리 추가 / 수정
d['d'] = 4
d['a'] += 3 # d = {'a':4, 'b':2, 'c':3, 'd':4}
- zip 함수 (저장된 값 조합해 다수의 튜플 생성)
z = zip( ['a', 'b, 'c'], [1, 2, 3] ) # 두 개의 리스트에 저장된 값 조합
z = zip( ('a', 'b, 'c'), (1, 2, 3) ) # 두 개의 튜플에 저장된 값 조합
z = zip ('abc', (1, 2, 3) ) # 문자열과 튜플에 저장된 값 조합
➡ 결과 : ('a',1), ('b',2), ('c',3)
2. dict의 루핑 기술과 컴프리헨션
- 딕셔너리 메소드➡ 뷰 객체로 반환
- (1) dict.keys() : 딕셔너리 키들만 참조
(2) dict.values() : 딕셔너리 값들만 참조
(3) dict.items() : 딕셔너리 키와 값을 튜플 형태로 참조
d = dict(a = 1, b = 2, c = 3)
for k in d.keys():
print(k, end=',') # a, b, c,
for k in d.items(): # k, v 저장하면서 튜플 언패킹
print(k, v, end=',')
- dict 컴프리헨션
d1 = dict(a = 1, b = 2, c = 3)
d2 = {k : v*2 for k, v in d1.items()} # d1의 값을 2배 늘린 딕셔너리 생성
d3 = {k : v for k, v in d1.items() if v%2} # d1의 값이 홀수인 것만 모은 딕셔너리 생성
# zip함수 사용한 dict 컴프리헨션
ks = ['a, 'b', 'c', 'd']
vs = [1, 2, 3, 4]
d = {k : v for k, v in zip(ks, vs)}
3. dict & defaultdict
- setdefault 메소드 / defaultdict 함수 : 디폴트 값을 갖는 딕셔너리 생성
- ➡ 찾는 키가 없으면 예외를 발생시키지 않고 해당 키 추가
➡ 미리 등록해 놓은 함수가 반환하는 디폴트 값을 그 키의 값으로 저장
from collections import defaultdict
s = "robbot" s = "robbot"
d = {} d = defaultdict(int) # int 함수를 등록하면서 defaultdict 호출
for k in s: from k in s:
d[k] = d.setdefault(k, 0) + 1 d[k] += 1
➡ d = {'r' : 1, "o" : 2, "b" : 2, "t" : 1}
📁 집합
1. 자료형 분류와 set & frozenset
- set() : mutable 객체 (수정 가능)
- add : 원소 추가
- discard : 원소 삭제
- update (|=) : 다른 집합의 원소 전부 추가 (합집합)
- intersection_update (&=) : 다른 집합과 공통 원소만 남기기 (교집합)
- difference_update (-=) : 다른 집합이 갖는 원소 모두 삭제하기 (차집합)
- symmetric_difference_update (^=) : 공통으로 갖지 않는 원소 추가하고, 나머지 삭제
- frozenset() : immutable 객체 (수정 불가능)
os = {1, 2, 3, 4, 5}
os.add(6) # {1, 2, 3, 4, 5, 6}
os.discard(1) # {2, 3, 4, 5, 6}
os.update({7, 8, 9}) # {2, 3, 4, 5, 6, 7, 8, 9}
os &= {2, 4, 6, 8} # {2, 4, 6, 8}
os -= {2, 4} # {2, 4, 6, 8}
os ^= {1, 3, 6}
📁 문자열
1. enumerate와 문자열 비교
- 문자열 비교 : sort, sorted 메소드 / "가" < "나"
- enumerate 함수 : iterable 객체를 인자로 전달 받아 전달된 값을 하나씩 반환
# Q. 이름 정렬하고 1부터 시작해서 번호 매기고, 번호가 "키"이고 이름이 "값"이 되어 딕셔너리에 저장
names = ["윤", "김", "장", "이", "박"]
names.sort() dnames = {k: v for k, v in numerate(sorted(names), 1)}
dnames = {}
i = 1
for n in names;
dnames[i] = n
i += 1
➡ dnames = {1: "김", 2: "박", 3: "윤", 4: "이", 5: "장"}
2. 표현식 기반 문자열 조합
- "%s_%s" % (value, value) : 표현식 기반 문자열 조합
- %[flags][width][.precision]f
- flags : - (왼쪽 정렬하여 출력) / 0 (공백 대신 0 붙여 출력) / + (부호 출력)
- width : 폭, 어느정도 넓이 확보하고 출력할지 결정
- .precision : 정밀도, 소수 이하 몇째 자리 출력할지 결정
- "%(key)s_%(key)s" % {key : value, key : value} : 딕셔너리로 출력 대상 지정
3. 메소드 기반 문자열 조합
- "{ }_{ }".format(value, value) : 메소드 호출 통해 문자열 조합
- {0}, {1} : 몇 번째 전달인자로 대체
- {0:[flags][width][.precision]f}
- "{key}_{key}".format(key = value, key = value) : 딕셔너리로 출력 대상 지정
📂 클래스
1. 클래스와 객체의 본질
- 클래스 : 클래스 내에 들어갈 변수(데이터)와 메소드(기능)를 결정하는 것
- 파이썬 클래스 특징
- 변수 선언할 필요가 없음 (객체 생성하고 메소드 호출 가능)
- init 메소드즐 정의하여 변수 초기화 해주면, 변수 호출 관련 오류 이슈 없음
- 클래스에 속하는 변수 만들 수 있음
class Simple:
def __init__(self):
self.i = 0
def seti(self, i): # 메소드 정의
self.i = i # i 변수 생성
def geti(self):
return self.i
s1 = Simple()
s1.seti(200) # 객체 내에서 변수 대상으로 대입 연산 처음 진행시, 변수 생성
Simple.n = 7 # Simple 클래스에 변수 n 추가하고 7로 초기화
print(s1.n, s1.geti, sep=",") # 7, 3
2. 상속
- 부모 / 슈퍼 / 상위 클래스 ➡ 자식 / 서브 / 하위 클래스
- 상속 특징
- 부모 클래스가 갖는 모든 메소드가 자식 클래스에 담기고, 별도의 메소드 추가 가능
- 메소드 오버라이딩 : 상속 관계에서 동일한 이름의 메소드를 정의하는 것
- 자식 클래스의 init은 부모의 변수를 초기화할 값도 함께 전달받아야 함
class Father:
def run(self):
print("fast")
class Mather:
def dive(self):
print("deep")
class Son(Father, Mother): # Father, Mother 클래스 동시 상속
def run(self): # Father 클래스의 run메소드 오버라이딩
pirnt("high")
def run2(self):
super().run() # 부모 클래스의 run 호출 방법
def main():
s = Son()
s.run() # Son의 run 메소드 호출
s.jump()
3. isinstance 함수와 object 클래스
- isinstance(object, classinfo) : 객체의 클래스 유형을 확인하는 함수
class Fruit:
pass # 빈 클래스 정의하는 방법
class Apple(Fruit):
pass
class SuperApple(Apple):
pass
s = SuperApple()
isinstance(s, SuperApple) # True (s가 SuperApple 클래스의 객체인가)
isinstance(s, Apple) # True (SuperApple 클래스는 Apple을 직접 상속함으로써 Fruit 클래스 간접 상속함)
isinstance(s, Fruit) # True
- object 클래스 : 파이썬의 모든 클래스는 object 클래스를 간접 상속 한다
4. 스페셜 메소드
- 스페셜 메소드 : 파이썬에 의해 호출되는 메소드 (ex. init, len, iter, str)
len(t) # t.__len__()
itr = iter(t) # itr = t.__iter__()
s= str(t) # s = t.__str__()
class Car:
def __init__(self, id):
self.id = id
def __len__(self):
return len(self.id) # 7
def __str__(self):
return "Vehicle number : " + self.id # Vehicle number : 32러5234
def __iter__(self):
return iter(self.id) # 3 2 러 5 2 3 4
5. 연산자 오버로딩
- 연산자 오버로딩 : 연산을 진행했을 때 이를 대신해서 미리 약속해 놓은 메소드가 호출되도록 하는 것
6. 클래스 메소드와 static 메소드
- static 메소드
- 객체가 아닌 클래스에 속한 메소드라서 첫 번째 인자로 self를 전달받지 않음
- 클래스 이름을 통해 호출 가능
- 객체를 통해서 출 가능
class Father:
def run():
print("fast")
run = staticmethon(run) # run 메소드를 static 메소드로 만드는 방법
📖출처📖
윤성우의 열혈 파이썬 중급편
728x90
반응형
'BE > Python' 카테고리의 다른 글
| Python 특징 (0) | 2025.04.10 |
|---|---|
| 알고리즘 - 그리디, 구현 (0) | 2025.04.10 |
| 백준 - 조건문, 반복문, 배열 (0) | 2025.04.10 |