본문 바로가기
카테고리 없음

[강의] 우리를 위한 프로그래밍 : 파이썬 중급

by hsro2228 2021. 9. 29.

<우리를 위한 프로그래밍 : 파이썬 중급>(인프런)을 학습하고 개인 학습용으로 정리한 내용입니다

클래스 변수와 인스턴스 변수

- 클래스 변수는 클래스 내부에 선언되어 있어 모든 인스턴스가 공유한다.

- 인스턴스 변수는 해당 인스턴스 내에서만 사용되는 변수로 앞에 'self.' 가 붙게 된다.

- 파이썬 코드에서 특정 변수를 확인할 때 인스턴스 변수 먼저 확인하고 없으면 클래스 변수를 확인한다.

class Account:
    num_accounts = 0 // 클래스 변수
    
    def __init__(self, name):
            self.name = name // 인스턴스 변수

클래스 메소드

- 클래스 내 메소드에는 class, instance, static 3가지 종류가 있다.

- 클래스 메소드에는 @classmethod 데코레이터가 붙는다.

   => 클래스 변수를 직접 핸들링하는 것보다 클래스 메소드를 호출하는 것이 더 좋은 방법이다.

- 인스턴스 메소드의 self 처럼 클래스 메소드의 첫번째 매개변수에 cls를 지정해주어야 한다.

@classmethod
def raise_price(cls, per):
    if per <= 1:
    	print('Please Enter 1 or More')
        return
    cls.price_per_raise = per
    return 'success'

매직 메소드

- 클래스 안에 미리 선언되어 있는 특별한 빌트인 메소드들을 매직 메소드라 부르며 메소드 명 앞,뒤에 '__' 더블 언더 스코어가 붙어있다.

- 일반적인 +, * 등의 사칙연산은 실은 __add__, __mul__ 매직 메소드가 실행되는 것이다.

- 매직 메소드를 활용하여 클래스간 연산을 직접 정의(매직 모소드 오버라이딩)해서 사용할 수 있다.

class Fruit:
    def __init__(self, name, price):
        self._name = name
        self._price = price
        
    def __add__(self, x):
    	return self._price _ x._price
        
# 인스턴스 생성
s1 = Fruit('Orange', 7500)
s2 = Fruit('Banana', 3000)

# 일반적인 계산
print(s1._price + s2._price)

# 매직 메소드 활용
print(s1 + s2)
# *arg 활용
class Vector(obejct):
	def __init__(self, *args):

		if len(args) == 0:
			self._x, self._y = 0, 0
		else:
			self._x, self._y = args

	def __add__(self, other):
		return Vector(self._x + other._x, self._y + other._y)

	def __bool__(self):
		return bool(max(self._x, self._y))

namedtuple

- 이름을 가진 튜플 형식의 자료구조

- 튜플의 기본 성질인 불변 객체의 성질을 가지고 있다.

- 일반 class 타입보다 적은 메모리만을 사용한다.

- Dictionary Key 와 같이 key를 통해 값을 호출해서 사용할 수 있다.

 

namedtuple 선언 방법

Point1 = namedtyple('Point', ['x', 'y'])
Point2 = namedtyple('Point', 'x,  y')
Point3 = namedtyple('Point', 'x y')

from collections import namedtuple

# 네엠트 튜플 선언
Point = namedtuple('Point', 'x y')

# 두 점 선언
p1 = Point(1, 3)
p2 = Point(x = 10, y = 12)

# 호출
print(p1[0] + p2[1])
print(p1.x + p2.y) // 클래스 변수처럼 사용 가능

# 다른 활용 예
Classes = namedtuble('Classes', ['rank', 'number'])

이터레이터(Iterator)

- __next__ 를 호출할 때 다음 값을 생성해내는 상태를 가진 헬퍼 객체를 말한다. 즉, __next()__을 가진 모든 객체는 이터레이터이다.

-  이터레이터는 값 생성기이다. 다음 값을 요청할 때마다 내부 상태를 유지하고 있기 때문에 다음 값을 계산하는 방법을 알고 있다.

 

제너레이터(Generator)

- 이터레이터의 특수한 한 형태이다. 함수 안에 yield를 사용하여 데이터를 하나씩 리턴하는 함수이다. 

- 제너레이터 함수가 다시 호출되면, 직전에 실행되었던 yield 문 다음부터 다음 yield 문을 만날 때까지 문장들을 실행하게 된다. 

- ex) 데이터가 무제한 이어서 모든 데이터를 리턴할 수 없는 경우나, 데이터가 대량이어서 일부씩 처리하는 것이 필요한 경우, 모든 데이터를 미리 계산하면 속도가 느려서 그때 그때 On Demand로 처리하는 것이 좋은 경우 등등 종종 사용된다.

 

클로저

- 클로저란 퍼스트클래스 함수를 지원하는 언어의 네임 바인딩 기술이다. 클로저는 어떤 함수를 함수 자신이 가지고 있는 환경과 함께 저장한 레코드이다

-  클로저는 ‘자신을 둘러싼 스코프(네임스페이스)의 상태값을 기억하는 함수’다.

- 클로저는 자체 스코프를 가지고 있어, cache 라는 상태는 매번 실행할 때마다 초기화되는 것이 아니라 값이 유지되고 있다. 마치 전역공간에 선언이라도 했듯이 말이다.

 

클로저 사용 조건

- 해당 함수는 어떤 함수 내의 중첩된 함수여야 한다.

- 해당 함수는 자신을 둘러싼(enclose) 함수 내의 상태값을 반드시 참조해야 한다.

- 해당 함수를 둘러싼 함수는 이 함수를 반환해야 한다.

클로저 장점

- 관리와 책임을 명확히 할 수 있다

- 각 변수가 섞여 불필요한 충돌을 방지할 수 있다

- 사용환경(context)에 맞게 임의대로 내부구조를 조정할 수 있다.

def closure_ex():
    # Free variable
    series = []
    
    # 클로저 영역
    def averager(v):
    	seried.append(v)
        return sum(seried) / len(seried)
    
    return averager

avg_closure1 = closure_ex()
print(avg_closure1(15))

코루틴

- 단일 스레드, 스택을 기반으로 동작하는 비동기 작업

- 서브 <-> 메인 (양방향 통신), send를 통해 서브 => 메인

- 단일 스레드, 스택을 기반으로 동작하는 비동기 작업

- 코루틴 : 루틴 실행 중 중지 -> 동시성 프로그래밍

=> 쓰레드에 비해 오버헤드 감소

- 쓰레드 : 싱글스레드 -> 멀티스레드 -> 복잡 -> 공유되는 자원 -> 교착 상태 발생 가능성, 컨텍스트 스위칭 비용 발생

 

Futures

- python에서 비동기 실행을 간편하게 사용할 수 있도록 만들어놓은 모듈

import os
import time
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, as_completed

WORK_LIST = [10000, 1000000, 1000000, 10000000]

def sum_generator(n):
	return sum(n for n in range(1, n+1))

def main():
	futures_list = []
    
    # 방법 1
    with futures.ThreadPoolExecutor() as excutor:
    	# map -> 작업 순서 유지, 즉시 실행
        result = excutor.map(sum_generator, WORK_LIST)
    
    # 방법 2
	with ThreadPoolExecutor() as excutor:
    	for work in WORK_LIST:
    	    future = excutor.submit(sum_generator, work)
            # 스케줄링
            futures_list.append(future)

 

참고자료

[인프런]우리를 위한 프로그래밍 : 파이썬 중급

https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A4%91%EA%B8%89-%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%98%A4%EB%A6%AC%EC%A7%80%EB%84%90

댓글