레퍼런스 카운트 : 객체를 참조하는 변수의 수
가비지 컬렉션 : 메모리 공간에 변수 등의 소멸 규칙 및 과정
➡ 레퍼런스 카운트가 0이 되면 가비지 컬렉션 대상
r1 = [1, 2, 3] # 리스트의 레퍼런스 카운트 = 1
r2 = r1 # 리스트의 레퍼런스 카운트 = 2
r1 = "python" # 리스트의 레퍼런스 카운트 = 1
r2 = "easy" # 리스트의 레퍼런스 카운트 = 0 (가비지 컬렉션 대상)
객체 비교시 사용하는 연산자
(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)
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 객체
람다 함수 : 이름 없는 함수 정의
lambda [매개변수 선언] : [표현식]
➡ 람다 함수 : 이름 없는 함수 정의
➡ 매개변수 : 없을 경우 생략 가능
➡ 표현식 : 함수 호출 가능
def 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)))
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 도 제너레이터 종류
# 1부터 10까지 제곱
generator = (i**2 for i in range(1, 10)) # next() 통해 호출
comprehension = [i**2 for i in range(1, 10)] # 리스트에 저장
객체 전달 과정
함수 정의 과정
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}
a = [] == [x for x in rage(10)]
for i in range(10):
a.append(i)
a = [] == [i for i in range(10) if i % 2]
for i in range(10):
if i % 2:
a.append(i)
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)
st = list(range(1, 11))
fst = [n**2 for n in st]
st = list(range(1, 11))
fst = [n for n in st if not(n % 3)]
st = list(range(1, 11))
fst = [n**2 for n in st if (n**2) % 3 == 0]
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)
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
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}
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)
딕셔너리 메소드
(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=',')
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)}
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}
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}
# 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: "장"}
클래스 : 클래스 내에 들어갈 변수(데이터)와 메소드(기능)를 결정하는 것
파이썬 클래스 특징
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
부모 / 슈퍼 / 상위 클래스 ➡ 자식 / 서브 / 하위 클래스
상속 특징
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()
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
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
class Father:
def run():
print("fast")
run = staticmethon(run) # run 메소드를 static 메소드로 만드는 방법
윤성우의 열혈 파이썬 중급편