Python - 개념

수현·2022년 11월 21일
0

Book

목록 보기
1/12
post-thumbnail

📂 레퍼런스 카운트와 가비지 컬렉션

  • 레퍼런스 카운트 : 객체를 참조하는 변수의 수

  • 가비지 컬렉션 : 메모리 공간에 변수 등의 소멸 규칙 및 과정

    ➡ 레퍼런스 카운트가 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 [매개변수 선언] : [표현식]

    ➡ 람다 함수 : 이름 없는 함수 정의
    ➡ 매개변수 : 없을 경우 생략 가능
    ➡ 표현식 : 함수 호출 가능

    def show(a, b):    ==   ref = lambda a, b : a + b
    	return a + b		 ref = (3, 4)
       
    ref = show(3, 4)

    2. map & filter

  • 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 메소드로 만드는 방법    

📖출처📖

윤성우의 열혈 파이썬 중급편

profile
Notion으로 이동 (https://24tngus.notion.site/3a6883f0f47041fe8045ef330a147da3?v=973a0b5ec78a4462bac8010e3b4cd5c0&pvs=4)

0개의 댓글