TIl

OOP1

아크몽 2024. 1. 24. 23:48

절차 지향 프로그래밍 Procedural Programming

프로그램을 ‘데이터’와 ‘절차’로 구성하는 방식의 프로그래밍 패러다임

순서 중시

특징

  • 데이터와 해당 데이터를 처리하는 함수(절차)가 분리되어 있으며, 함수 호출의 흐름이 중요
  • 코드의 순차적인 흐름이 함수 중심

    함수 호출의 순서가 중요한 패러다임이다.

    함수랑 데이터는 별도로 분리되어있다.

    ⇒ 프로그램의 전체적 흐름을 함수가 이끈다

  • 데이터를 다시 재사용하는 것 보다는 처음부터 끝까지 실행되는 결과물을 중시

단점 : 소프트웨어 위기(Software Crisis)

하드웨어의 발전⇒ 컴퓨터 계산 용량과 문제의 복잡성이 급격히 증가 ⇒ 소프트웨어가 따라가지 못해서 생긴 충격

function3 에 문제가 생기면 function3을 활용해야만 하는 프로그램들이 고장난다. (= 절차 중간에 문제가 생겼을 때 소프트웨어가 무너지는 현상이 발생)

⇒ 새로운 패러다임의 필요

⇒ 객체 지향 프로그래밍 등장

데이터는 함수의 재료로서 쓰이는 식 이었다.

객체 지향 프로그래밍 Object Oriented Programming(OOP)

데이터와 해당 데이터를 조작하는 메서드를 하나의 객체로 묶어 관리하는 방식의 프로그래밍 패러다임

데이터와 함수를 같이 묶어서 생각한다. ⇒ 관점이 변했다.

전사 마법사 예

절차 : 공격을 한다(전사가) ↔ 객체: 전사가 베기를 한다, 마법사가 회북을 한다.

캐릭터(부모) 와 전사,마법사(자식) 간의 상하관계가 보인다.(클래스가 중심이 된다.)

↔ 절차 지향에서는 공격,수비(함수들)이 중요했다.

절차 지향 vs 객체 지향

절차지향
  • 데이터와 해당 데이터를 처리하는 함수(절차)가 분리
  • 함수 호출의 흐름이 중요
객체 지향
  • 데이터와 해당 데이터를 처리하는 메서드(메시지)를 하나의 객체(클래스)로 묶음
  • 객체 간 상호작용과 메시지 전달이 중요

객체지향은 비교적 순서를 중요하게 생각하지 않는다.

클래스 Class 붕어틀

파이썬에서 타입을 표현하는 방법

  • 객체를 생성하기 위한 설계도, 하지만 Class도 객체다
  • 데이터(변수)와 기능(함수, 메소드)을 함께 묶는 방법을 제공
  • print(type(x)) ⇒ <'class' ‘str’>
  • 가수(클래스)로 특정 가수들(객체)를 찍어낸다. ⇒ blue print (청사진) 처럼 쓰인다.

객체 object 붕어빵

클래스에서 정의한 것을 토대로 실제로 메모리에 할당된 것

파이썬의 모든 것은 객체 (변수, 함수, 클래스 무엇이든 넓은 개념)

속성(정보)(변수)행동(동작)(메서드)으로 구성된 모든 것

붕어 틀을 먹을 순 없으니 붕어빵을 먹어야 한다.

클래스와 객체

인스턴스 : 클래스로 만든 객체

많은 객체들이 있지만 클래스를 통해서 만든 객체를 특별히 인스턴스라고 불러준다.

  • 클래스를 만든다 == 타입을 만든다
  • 클래스 안에 변수와 메서드
  • 변수 name의 타입은 str class

    ⇒변수 name은 str 클래스의 인스턴스이다.

    ⇒ 결국 문자열 타입의 변수는 str 클래스로 만든 인스턴스다.

⇒ 우리가 사용해왔던 데이터 타입은 사실 모두 클래스였다.

name = 'Alice'
print(type(name)) #
print(help(str)) # class str(object)~~~
문자열 타입( Class )의 객체( instance )
‘’, ’hello. ’파이썬’

리스트 타입(Class )의 객체 (instance ) 
[1,2,3], [1], [], ['hi']

class str라는 거대한 객체 안에 .upper라는 함수가 존재함 ⇒ 메서드로 사용 가능

흐름

’hello’.upper()

문자열.대문자로( ) ⇒ 객체.행동( ) ⇒ 인스턴스.메서드( )

[1,2,3].sort()

리스트.정렬해() ⇒ 객체.행동() ⇒ 인스턴스.메서드()

⇒ 메서드도 함수지만 함수(변수) 가 아닌 인스턴스.메서드()로 쓰는 이유

하나의 객체(object)는 특정 타입의 인스턴스(instance)이다.

  • 문자열 데이터들은 모두 string클래스의 인스턴스
  • 리스트 데이터들은 모두 list클래스의 인스턴스

객체의 특징

타입: 어떤 연산자(poerator) 와 조작(method)이 가능한가?

속성(attribute): 어떤 상태(데이터)를가지는가?

조작법(method): 어떤 행위(함수)를 할 수 있는가?

⇒ 객체 = 속성 + 기능(Method)

클래스 (다시 알아보기)

데이터와 기능을 함꼐 묶는 방법을 제공

# 클래스 정의
class Person: # 왜 대문자일까? PascalCase 표기법 차이
  pass    # snake_case도 가능 but 사회적 합의로 인해 표기법을 다르게 함    # 클래스 정의할 때 () 생략 가능
# 인스턴스 생성
iu = Person() # 원래는 변수겠지만, OOP 의 관점에서 인스턴스라고 한다.
# '인스턴스 변수 = 생성자 함수' 형태

# 메서드 호출
iu.메서드()

# 속성(변수) 접근
iu.attribute

Class는 병사를 생성하고 메서드와 속성을 제공해주고, 병사는 메서드와 속성을 자기가 활용한다.

클래스 기본 활용

class Person:   # 속성   blood_color = 'red' #클래스 변수    def __init__(self, name): # 이건 인스턴스가 못씀, name은 인스터스가 가지는 변수     self.name = name #인스턴스 변수, 우항 name은 파라미터     pass      # 메서드   def singing(self):     return f'{self.name}가 노래합니다.'   
# 인스턴스 생성
singer1 = Person('iu') # 클래스(인자)
singer2 = Person('BTS')


# 메서드를 호출
print(singer1.singing()) #iu가 노래합니다.
print(singer2.singing()) #BTS가 노래합니다.
# 설계도는 다른데, 결과는 다르다.

print(singer1.blood_color) # red
print(singer2.blood_color) # red

생성자 함수 def __init__(self, name):

객체를 생성할 때 자동으로 호출하는 특별한 메서드

매직 메서드의 한 종류(__함수이름__)

객체의 초기화를 담당, 초기 값이 필요하다고 하면 쓰임

기본생성자: 파라미터가 없다. Person() 으로만 쓰는것

인스턴스 변수 self.name = name

인스턴스(객체)마다 별도로 유지되는 변수

인스턴스마다 독립적인 값 가짐, 인스턴스가 생성 될 때마다 초기화됨

인스턴스들이 같은 공간을 공유하지 않음

클래스 변수 blood_color = 'red'

모든 인스턴스들이 공유(참조)하는 변수, 참조 가 가지는 특징 가진다

인스턴스 메서드 def singing(self):

인스턴스가 쓰는 메서드니까 인스턴스 메서드

클래스는 이 메서드를 관리만 할 뿐 쓰는 것은 인스턴스니까

각각의 인스턴스 변수에 접근하고 수정하는 등의 작업을 수행

인스턴스와 클래스 간의 이름 공간 (namespace)

클래스 정의 ⇒ 클래스 & 해당하는 namespace 생성

인스턴스를 만들면, 인스턴스 객체가 생성되고 독립적인 namespace 생성

⇒ 인스턴스를 만들 떄 마다 전혀 다른 공간을 부여받는다.

어떠한 인스턴스가 인스턴스.ssafy 라는 속성값을 접근하려 하면 일단 본인한테 있는지 확인 ⇒ Class가 가지고 있는지 찾아 올라간다.

독립적인 이름공간이 가지는 이점

  • 각 인스턴스는 독립적인 메모리 공간 가짐

    ⇒ 클래스와 다른 인스턴스 간에는 서로의 데이터나 상태에 직접적인 접근이 불가능

  • 객체 지향 프로그래밍의 중요한 특성 중 하나로,

    클래스와 인스턴스를 모듈화하고 각각의 객체가 독립적으로 동작하도록 보장

  • 이를 통해 클래스와 인스턴스는 다른 객체들과의 상호작용에서 서로 충돌이나 영향을 주지 않으면서 독립적으로 동작 가능

⇒ 코드의 가독성, 유지보수성, 재사용성을 높이는데 도움을 줌

가장 큰 절차지향과 객체지향의 가장 궁극적인 차이점 하나

순서를 가진다 ⇒ 서로 복잡하게 영향을 준다 . 2번은 3번에 반드시 영향을 준다.

클래스 변수 활용

가수가 몇 명인지 확인하고 싶다면?

인스턴스가 생성 될 때마다 __init__실행됨 ⇒ 이를 이용해서 정수 형태의 클래스 변수가 늘어나도록 설정할 수 있음

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

클래스 변수를 변경할 때는 항상 클래스.클래스변수 형식으로 변경

self 가 붙는다 = self 변수

LEGB 처럼 움직인다. (local → enclosed → global → built-in)

c2.pi = 5 : c2의 인스턴스 변수 pi에 값을 할당 =⇒ Class 변수와 상관 없다

메서드 종류 (용도를 나눠둔것)

  • 인스턴스 메서드
  • 클래스 메서드
  • 정적 메서드

인스턴스 메서드 instance

클래스로부터 생성된 각 인스턴스에서 호출할 수 있는 메서드

⇒ 인스턴스의 상태를 조작하거나 동작을 수행

인스턴스 메서드는 클래스를 조작하진 않음

인스턴스 메서드 구조

반드시 첫 번째 매개변수로 인스턴스 자기 자신(self)을 전달 받음

클래스 내부에 정의되는 메서드의 기본

class MyClass:
  def instance_method(self, arg1, ...):  # 문법상 'self' 가 아닌 다른 이름도 괜찮음 but 암묵적인 합의로 self를 쓰자
    pass

self 동작 원리

  • upper 메서드를 사용

    ‘hello’.upper()

  • 하지만 실제 파이썬 내부 동작 str.upper('hello')
  • str 클래스가 upper 메서드를 호출 ⇒ 첫 번째 인자로 문자열 인스턴스(’hello’)가 들어감

⇒ 인스턴스 메서드의 첫번째 매개변수가 반드시 인스턴스 자기 자신인 이유

  • ‘hello’.upper()str.upper('hello')객체 지향 방식메서드로 호출하는 표현(단축형 호출)
  • ‘hello’ 라는 문자열 객체가 단순히 어딘가의 함수로 들어가는 인자가 아닌 객체 스스로 메서드를 호출하여 코드를 동작하는 객체 지향적 표현

생성자 메서드 constructor

인스턴스 객체가 생성될 때 자동으로 호출되는 메서드

⇒ 인스턴스 변수들의 초기값을 설정 def __init__(self):

구조

class Person:
  def __init__(self):
    print('인스턴스 생성')
# 인스턴스가 만들어지면 __init__이 바로 실행됨
person1 = Person() # 인스턴스 생성

클래스 메서드 clas

클래스가 호출하는 메서드

⇒ 클래스 변수조작 or 클래스 level의 동작을 수행

클래스 메서드 구조

  1. @classmethod 데코레이터를 사용하여 정의, 없으면 인스턴스 메서드다.

    꾸며주는 함수그냥 업그레이드 해주는 느낌으로 기억하고 있으면 됨

  2. 호출 시, 첫번째 인자로 호출하는 클래스(cls)가 전달됨
    cls 도 단순한 매개변수 이름, 바꿔도 됨 But 암묵적인 합의에 의해 금지함

    ⇒ 상속을 위해 MyClass.count 가 아닌 cls.count 를 쓴다.

class MyClass:
count = 0
  @classmethod
  def class_method(cls, arg1, ...) #cls 를 self로 써도 문제는 발생 X  print(cls.count)
    pass

스테틱(정적) 메서드 static

클래스와 인스턴스와 상관없이 독립적으로 동작하는 메서드

⇒ 주로 클래스와 관련, but 인스턴스와 상호작용이 필요X 할 때 사용

일반함수처럼 쓰는 함수들

구조

@staticmethod 데코레이터를 사용하여 정의

호출 시 필수적으로 작성해야 할 매개변수 X

즉, 객체 상태나 클래스 상태를 수정X == 단지 기능(행동)만을 위한 메서드로 사용

클래스.스태틱메소드 식으로 사용

각자의 역할

Class가 사용해야 할 것
  • 클래스 Method
  • 스태틱 Method
  • 인스턴스 Method(호출은 가능, 권장 X)
인스턴스가 사용해야 할 것
  • 인스턴스 Method
  • 클래스, 스태틱 Method {호출은 가능함(거슬러 올라갈 수 있어서) but 권장 X}

  • 클래스는 모든 메서드를 호출 할 수 있음

    But 클래스는 클래스 메서드와 스태틱 메서드만 사용하도록 한다.

  • 인스턴스도 모든 메서드를 호출 할 수 있음

    But 인스턴스는 인스턴스 메서드만 쓰도록 하자

⇒ 할수있다 ≠ 써도 된다.

각각의 메서드는 OOP 패러다임에 따라 명확한 목적에 따라 설계된 것이기 때문에 클래스와 인스턴스 각각 올바른 메서드만 사용하도록 해야 한다.

파이썬은 규칙이 강하진 않다 ⇒ 자유성은 높음, 하지만 실수가 많아 질 수 있다.

매직 메서드

  • 범주를 따지면 인스턴스 메서드에 속함
  • 특정 상황에 자동으로 호출되는 메서드 ⇒ 직접활용할 일은 잘 없다
  • Double underscore(__) 가 있는 메서드는 특수한 동작을 위해 만들어진 메서드
  • 스페셜 or 매직 메서드라고 불림
  • 첫 매개변수는 무조건 self

예시

__-str__(self), __len__(self) 
__lt__(self,other), le, eq, gt, ge, ne

데코레이터 Decorator

다른 함수의 코드를 유지한 채로 수정하거나 확장하기 위해 사용되는 함수

인자로 함수를 받아서 쓴다 → 원본 함수를 꾸며서 사용할 때 쓰는 편

def my_decorator(func): #my_function이 여기 매개함수로 들어감   def wrapper():     # 함수 실행 전에 수행할 작업     print('함수실행전')     # 원본 함수 호출     result = func()     # 함수 실행 후에 수행할 작업     print('함수 실행 후')     return result   return wrapper

@my_decorator
def my_function():   print('원본 함수 실행')

my_function()

"""
함수 실행 전
원본 함수 실행
함수 실행 후
"""
  

절차 지향과 객체 지향은 대조되는 개념 X

기본은 절차 지향인데 보완을 위해 객체라는 개념 도입

⇒ 상속, 코드 재사용성, 유지보수성 등 이점을 가지는 패러다임

추가로 배운것

class는 붕어빵 틀, object는 붕어빵이름, instance는 붕어빵

인스턴스 변수는 클래스 메서드를 조작 할 수 있다.

클래스 변수는 인스턴스 메서드를 조작할 수

객체지향 프로그램의 4가지 특징

  • 추상화 : 공통적이고 본질적인 특징을 추출하여 정의
  • 상속 : 기존에 구현한 클래스를 재활용
  • 다형성 : 같은 명령을 해도 다르게 결과가 나온다.
    • 삼각형에게 그려라삼각형을 그린다
    • 원에게 그려라을 그린다.
  • 캡슐화 : 필요한 메서드만 보여주고 내부는 보여주지 않는다

메모리 구조

code

data 전역 // Class

heap 동적 // 인스턴스

stack 지역