본문 바로가기
Appz Knowledge/Python

Python 혼공노트 5 - 클래스

by 스쳐가는인연 2023. 1. 30.

Python 혼공노트 5.

- 혼자 공부하는 파이썬(개정판) 청강하며... (그외 파이썬 강의도 …)

 

보다 나은 프로그램을 만드는 노력:

# 명령형(Imperative) 프로그래밍: 수행할 동작(How)에 중점을 둠

명령문을 사용해서 프로그램이 어떠한 동작을 할 지 순서대로 나열하는 프로그램 작성

 

# 선언형(Declarative) 프로그래밍: 수행 후 얻을 결과(What)에 중점을 둠

e.g.) html, SQL

 

# 절차적 프로그래밍

서브루틴, 프로시저, 함수

- 같은 코드를 여러 번 작성하지 말고, 함수를 만들어 사용

- GOTO 구문 또는 JUMP 구문 대신 함수를 사용

 

# 함수형 프로그래밍

함수는 수학적 개념임에, 순수 함수를 사용

 

# 객체 지향 프로그래밍

- 변수와 함수를 묶어 하나의 묶음을 통해 규모에 영향을 받지 않는 프로그램을 만들 수 있음

 

기존 기법/방식으로 작성하며 어려움에 직면함:

- 함수를 많이 사용하다 보니, 함수의 용도 및 존재를 파악하기 어려움 / 영향의 범위를 예측하기 어려움

- 함수를 카테고리로 구분(함수명에 용도를 예측 가능한 키워드를 사용)

> 객체를 중심으로 함수와 변수의 카테고리를 구분하는 단계로 발전

 

Python:

관심사로 카테고리 구분: 모듈

객채 지향 프로그래밍: 클래스

 

객체(object) = 속성 + 행위

 

클래스: 속성과 행위를 통합 (카멜표기법에서 대문자로 시작하는 명명 in Python)

       함수(와 변수)를 묶어 놓은 것 / 객체(인스턴스)를 생성하기 위한 설계도

 

class Class이름:

    #Class의 내용

    pass

    def __init__(self, 매개변수1, 매개변수2 ): # 생성자

        self.표현식

        self.__매개변수1 = 매개변수1 # “__”로 내가 의도하지 않은 속성의 데이터는 무시 / 외부에서의 접근 제한

        self.__매개변수2 = 매개변수2

    def __del__(self): # 소멸자

    def func(self)

        표현식

 

    # 필요시에만 생성: attribute

    def get_매개변수1(self):

        return self.__매개변수

def set_매개변수1(self, 매개변수1):

        return self.__매개변수1 = 매개변수1

 

# 필요시에만 생성: property

    @property

    def 매개변수1(self):

        return self.__매개변수

    @매개변수.setter

    def 매개변수1(self, 매개변수1):

        return self.__매개변수1 = 매개변수1

 

인스턴스(객체) = Class이름() # 클래스 호출

1) Class이름.func(인스턴스, 매개변수(s)) # 클래스 내부 함수(메소드) 호출

2) 인스턴스.func(매개변수(s)) # 클래스 내부 함수(메소드) 호출 / 자주 사용되는 방식

 

클래스(): 클래스의 속성을 설명

객체(실체화된 것)": 클래스에 대한 정보를 실제로 정의

실체화한 객체 = "인스턴스" #호출된 클래스

 

 

특수한 이름의 함수들: "__"로 시작하는 함수들

def __str__(self):      # 전달된 값을 문자열로 반환

    return "문자열"

 

def to_string(self):   # 같은 기능의 함수

    return "문자열"

 

def __add__(self, other): # self + other / 기존 내용에 추가

    return self

 

많이 사용되는 약어:

eq: ==, equal

ne: !=, not equal

gt: >, greater than

ge: >=, greater than or equal

lt: <, less than

le: <=, less than or equal

 

def __eq__(self, other):

    return self.속성 == other.속성

def __ne__(self, other):

    return self.속성 != other.속성

def __gt__(self, other):

    return self.속성 > other.속성

def __ge__(self, other):

    return self.속성 >= other.속성

def __lt__(self, other):

    return self.속성 < other.속성

def __le__(self, other):

    return self.속성 <= other.속성

 

# 값 객체 / 특정 자료의 단위의 혼동/불일치로 인한 동작/결과 오류를 방지하기 위해 클래스를 활용함

e.g.) in cm의 사용 등

Class CmLength:

    def __ init__(self, cm):

        if cm < 0:

            raise “length is bigger than ‘0’”

        self.__length = cm

    def get():

        return self.__cm

    def __add__(self, other):

        if type(other) != CmLength:

            raise “use same length”

        return CmLength(self.get() + other.get())

 

CmLength(3) + CmLength(10)

 

 

캡슐화 # 객체 사용자가 작성자가 의도하지 않은 동작/사용을 할 수 없도록 함수와 변수를 숨겨 제한하는 것

# 인스턴스 함수와 인스턴수 변수 앞에 “__”를 추가

캡슐화 한 경우, 변수를 직접 제어하는 것은 불가능하나, 별도 함수를 생성하여 가능하도록 할 수 있음

> 잘못된 사용을 예방하기 위한 예외 처리 용으로도 유용함

 

 

@property

def get_func(): # getter

    표현식

@set_func.setter.

def set_func(): # setter

    표현식

 

프로퍼티 # 캡슐화 한 상태이지만, 문법은 캡슐화하지 않은 상태처럼 동작하도록 할 수 있음

아래 키워드를 함수 위에 삽입하여 프로퍼티임을 명시

@property

@set_func.setter

 

 

상속(inheritance): 여러 함수들 중 반복되는 공통된 항목을 묶는 것

- 새로 정의하고자 하는 (자식)클래스가 부모클래스의 기능을 그대로 물려받으면서,

이중 특정 기능을 수정하고자 하거나, 추가적인 기능을 구현하고자 할 때

- 호출된 함수에서 필요한 함수가 없는 경우, 상위 클래스를 찾아 올라가게 됨

 

- 상속 관계가 복잡할 경우, 코드에 대해 이해가 어려워짐. 상속을 할 경우 위험성이 증가

- 상속 관계일 경우, 부모 클래스가 변하면 자식 클래스에 영향을 줌(함께/계속 수정되어야 함)

 

class Super_Class: # Parent class)

   def __init__(self):

  

class Sub_Class(Super_Class): # Child class

   def __init__(self, 매개변수):

  

 

Super_Class에는 공통된 기능에 대한 빼대/골자를 선언하고, 구체적인 기능은 Sub_Class에서 작성함

 

e.g.) 상속의 예

class Shape:

   def __init__(self):

      raise “생성자 구현

   def 넓이(self):

      raise “넓이 연산 및 반환 함수 구현

   def 출력보조(self):

      raise “출력 보조 함수 구현

   def 출력(self):

      print(“=” * 10)

      self.출력보조()

      print(f”넓이: {self.넓이()}”)

      print(“=” * 10)

     

class Circle(Shape):

   def __init__(self, 반지름):

      self.파이 = 3.14

      self.반지름 = 반지름

   def 출력보조(self):

      print(f”원의 반지름은 {self.반지름}”)

   def 넓이(self):

      return self.반지름 * self.반지름 * self.파이

 

circle = circle(10)

circle.출력()

 

class Square(Shape):

   def __init__(self, 길이):

      self.길이 = 길이

   def 출력보조(self):

      print(f”정사각형 한 변의 길이는 {self.길이}”)

   def 넓이(self):

      return self.길이 * self.길이

square = Square()

square.출력()

 

class Triangle:

class Rectangle:

class Ellipse:

 

오버라이드(override): Super_Class에 정의된 함수를 Sub_Class에서 재정의하여, Sub_Class의 기능으로 대체하는 것

 

class Super_Class:

   def function(self):

      print(“function of Super_Class”)

 

class Sub_Class:

   def function(self):

      print(“function of Sub_Class”

 

      #1 access Super class function

      Super_class.function(self)

      #2 access Super class function when don’t know which Super_Class / generally use this way

      super().function()

 

 

child = Sub_Class()

child.function() # call sub class function / generally use this way /

# call Super class function via defined #2 method too.

Sub_Class.fuction(child) # call Super class function via defined #1 method

 

 

컴포지션(Composition, Aggregation): 다른 클래스의 일부 메서드를 사용하고 싶지만, 상속은 하고 싶지 않을 경우

- 프레임워크에서 상속을 강제하지 않는 모든 경우에, 컴포지션을 사용

- 상속이나 컴포지션 모두 사용 가능하다면, 대부분의 경우 컴포지션을 사용 가능

 

- class를 상속받지 않고, 내부에 캡슐화하여 포함(“__” 키워드로 캡슐화)후 활용하는 방식

- class의 속성이 방대/강력한 경우, 의도치 않은 동작 발생 가능성이 급증함에, 해당 기능을 일부러 강제하여 최소화하는 것이 목적

 

상속: is-a, 암시적 선언 (자식에 없고 부모에 있을 수 있어서 암시)

컴포지션: has-a, 명시적 선언 (자식에 분명하게 명시)

 

 

stack : 선입후출(First in Last out, FILO) / 후입선출(Last in First out, LIFO) 구조를 갖는 자료 구조

push: 자료를 입력

pop: 자료를 출력

 

class Stack:

   def __init__(self):

      self.__list = []

   def push(self, value):

      self.__list.append(value)

   def pop(self):

      output = self.__list[-1]

      del self.__list[-1]

      return output

 

stack = Stack()

stack.push(10) # [10]

stack.push(20) # [10, 20]

stack.push(30) # [10, 20, 30]

print(stack.pop()) #30 [10, 20]

print(stack.pop()) #20 [10]

print(stack.pop()) #10

 

 

queue: 선입선출(First in First out, FIFO) 구조를 갖는 자료 구조

enqueue: 자료를 입력

dequeue: 자료를 출력

 

class Stack:

   def __init__(self):

      self.__list = []

   def enqueue(self, value):

      self.__list.append(value)

   def dequeue(self):

      output = self.__list[0]

      del self.__list[0]

      return output

 

queue = Queue()

queue.enqueue (10) # [10]

queue.enqueue (20) # [10, 20]

queue.enqueue (30) # [10, 20, 30]

print(queue.dequeue()) #10 [20, 30]

print(queue.dequeue()) #20 [30]

print(queue.dequeue()) #30

 

 

 

 

 

반응형