본문 바로가기
Study/PYTHON,Django

Python(4)-OOP심화

by 왕방개 2024. 1. 19.

객체지향 프로그래밍


1)함수형 프로그래밍 과 객체 지향 프로그래밍
=>함수형 프로그래밍은 기능 단위로 작성하는 프로그래밍 방식
유사한 동작을 하는 함수들은 파일로 묶어서 구분
이 방식의 장점은 일반적으로 속도가 빠르고 불필요한 내용을 포함하지 않습니다.
빅데이터 처리 분야에서 많이 사용합니다.

=>객체 지향 프로그래밍은 유사한 동작을 하는 함수 나 데이터를 하나로 묶어서 프로그래밍 하는 방식
유사한 동작을 하는 함수 와 데이터를 클래스라는 템플릿으로 묶고 템플릿을 이용해서 인스턴스를 생성해서 사용하는 방식으로 클래스도 하나의 인스턴스로 취급합니다.

2)객체 지향에서 중요한 3가지
=>Encapsulation(캡슐화): 클래스를 만들고 인스턴스를 만드는 것

=>Inheritance(상속): 상위 클래스의 모든 것을 하위 클래스가 물려받는 것
프레임워크에서는 대부분 제공되는 클래스의 기능을 확장하기 위해서 상속을 수행합니다.
객체 지향 프로그래밍의 기본 원칙에서는 여러 하위 클래스에 공통으로 존재하는 기능을 상위 클래스로 올려보내는 것으로 간주합니다.

상위 <- 하위

=>Polymorphism(다형성): 동일한 메시지에 대하여 다르게 반응하는 성질
동일한 코드가 인스턴스를 만든 클래스에 따라 다른 메서드를 호출하는 것
상속 과 오버라이딩으로 구현합니다.

3)클래스 와 인스턴스 만들기
=>클래스 만들기 
class 클래스이름:
내용 #내용을 나중에 만드는 경우는 pass 라고 적어도 됩니다.

=>클래스 와 함수 특징
클래스 와 함수를 만들면 모두가 접근할 수 있는 영역에 생성되고 프로그램을 종료할 때 까지 소멸되지 않습니다.

=>인스턴스 만들기: 메모리에 인스턴스를 생성하고 인스턴스의 참조(id)를 리턴)
클래스이름(매개변수 나열...)

=>인스턴스를 생성하고 참조하는 데이터가 없다면 언제인지는 알 수 없지만 자동으로 메모리 정리가 됩니다.

=>클래스에 작성할 수 있는 것
데이터(속성 - attribute)
클래스 속성: 클래스 안에 데이터를 만들고 클래스 와 인스턴스가 공동으로 사용하는 것
인스턴스 속성: 인스턴스 안에 만들어서 인스턴스만 사용할 수 있는 것

클래스 안에 변수를 만들면 이것은 클래스 속성이 됩니다.
메서드 안에서 메서드의 첫번째 매개변수이름.속성으로 만들면 이는 인스턴스 속성이 됩니다.

클래스 나 인스턴스를 이용해서 속성에 접근할 때는 내부에서는 이름만으로 가능하지만 외부에서는 클래스 나 인스턴스이름.속성으로 접근합니다.

기능(메서드)
클래스 안에 함수를 만들면 메서드(Method)
Method의 종류
초기화 메서드(init): 인스턴스를 만들 때 호출되는 메서드로 만들지 않아도 기본적으로 아무일도 하지 않는 초기화 메서드가 존재하며 다른 초기화 메서드를 만들면 이 메서드는 제거됩니다.
다른 언어에서는 생성자(Constructor)라고 합니다.

클래스 메서드, 스태틱 메서드: 클래스 안에 특별한 decorator 와 함께 만드는데 클래스 와 인스턴스 모두 호출 가능한 메서드
이 메서드는 인스턴스 속성을 만들 수 없고 소유할 수 없습니다.
목적은 인스턴스 속성이 필요없는 동작을 하고자 할 때 사용합니다.

인스턴스 메서드: 클래스 안에 만들어지는 함수로 무조건 1개의 매개변수(객체 자신의 참조)를 가지고 만들어지는 함수로 인스턴스만 호출할 수 있고 인스턴스 속성 생성이 가능합니다.

인스턴스 메서드 호출 방법
Bound 호출: 인스턴스.메서드(매개변수를 나열 - self 값을 대입하지 않음)
Unbound 호출: 클래스.메서드(인스턴스, self를 제외한 매개변수 대입)

인스턴스 메서드 안에서 첫번째매개변수.속성이름 = 값의 형태로 만들면 인스턴스 속성이 만들어집니다.
이 속성은 인스턴스 이름으로 접근하고 인스턴스마다 별도로 만들어 집니다.


=>실습 코드
#자동차를 표현하는 클래스
#일반적으로 클래스 이름은 대문자로 시작하고 단어의 시작마다 첫글자를 대문자로 합니다.

class Car:
    #클래스 속성 - 클래스 와 인스턴스 모두 접근 가능, 공유
    maker = "KIA"

    #인스턴스 메서드 - 첫번째 매개변수는 인스턴스 자신의 참조(필수)
    def method(self):
        print("인스턴스 메서드")

#Car 클래스의 인스턴스를 생성
car = Car()

print(car.maker)
print(Car.maker)

Car.maker = "Ford"
print(car.maker)
print(Car.maker)

#메서드 호출
#바운드 호출
car.method()
#언바운드 호출
Car.method(car)

#print(help(str))

x = "hello"
print(x.capitalize())
print(str.capitalize(x))


#print(help(list.sort))
li = [100, 20, 30, 90]
li.sort(reverse=True)
print(li)
print(li.sort())



=>데이터 분류
mutable 과 immutable: mutable은 변경 가능한 데이터이고 immutable은 변경 불가능한 데이터
(variable)    (constant + literal)

scala data 와 vector data: scala data 는 1개의 데이터이고 vector data는 0개 이상의 데이터 모임
scala data는 참조 자체가 데이터이고 vector data는 참조가 데이터의 시작 위치를 의미하고 세부 데이터는 인덱스나 키를 이용해서 접근합니다.

정형 데이터: 모양이 동일한 데이터, 테이블 형태의 데이터

비정형 데이터: 모양이 일정하지 않은 데이터로 텍스트 와 음성

반정형 데이터: 대부분의 경우 텍스트인데 메타 데이터를 확인하면 정형 데이터로 변경가능한 데이터
csv, tsv, txt, json, xml, yaml 등

[1,"a"] 이 둘은 서로 같은 자료형이다.  왜냐면 id 형태로 저장되기 때문이다. 그 id안에 있는 데이터 자료형이 다른거.

map-key와 value의 집합 형태로 데이터를 저장함.map도 list처럼 열려있음

객체지향은 class을 어떻게 만들것인가를 공부하는 것임

literal 은 static 메모리에 모아두고 저장하는 것

4.Accessor(getter와 setter,접근자 메서드)
=> 인스턴스가 소유한 속성의 값을 수정하거나 읽기 위한 메서드
=>값을 읽는 메서드를 getter라 하고 값을 수정하는 메서드를 setter 라고 합니다
이렇게 속성이 getter 와 setter를 소유하면 property라고 합니다

1)gettter
=>속성의 값을 읽기 위한 메서드
=>관습적으로 이름은 get속성이름(self) 로 만들고 속성의 값을 리턴합니다
=>속성의 자료형이 bool인 경우 get대신 is를 사용
=>이 메서드는 동시에 접근해도 됨
=>메서드 이름에서 속성이름의 첫글자는 대문자로 합니다

2)setter
=>속성의 값을 수정하기 위한 메서드
=>관습적으로 이름은 set속성이름(self,속성이름)으로 만들고 내용은 매개변수로 받은 데이터를 속성에 대입
=>리턴하는 데이터는 None
=>이 메서드는 동시에 접근하면 됩니다
=>메서드 이름에서 속성이름의 첫글자는 대문자로 합니다

__ __ => 특수한 형태로 불러와야해


파이썬의method 이름 관습
=>첫글자를 대문자를 사용해야 하는 경우 _로 시작하고 소문자로 시작하기도 합니다
>__로 시작하면 직접 접근이 안되는 메서드입니다.(private)
=>__로 시작하고, __로 끝나면 직접 호출하지 않고 다른 방법으로 호출을 합니다


5.초기화 메서드와 ★소멸될 떄 호출되는 메서드
=>예전에는 생성자 와 소멸자라는 표현을 많이 사용
=>생성자는 메모리할당과 초기화 두가지 작업을 수행하는 특별한 메서드이고 초기화 메서드는 초기화만 담당하는 메서드
=>file handling,database,network programming을 할땐 exception handling을 반드시 해야함
exception handling이란? 문제가 생기면 그냥 좀 넘어가자 

1)기화 메서드 - __init__
=>인스턴스를 만들때 호출하는 메서드
=>기본적으로 매개변수가 self 1개인 메서드가 제공됩니다
기본적으로 제공되는 __init__은 아무일도 하지 않습니다
=>무엇인가를 하도록 하려면 __init__재정의(overriding)해야 합니다
직접 재정의를 하게 되면 기본적으로 제공되는 메서드는 없어집니다.
=>인스턴스가 생성 될 떄 주로 하는 일은 인스턴스 속성(attribute)을 만들어서 초기화 하는 작업입니다.
이 때 외부에서 만든 데이터를 인스턴스 속성에 대입하는 경우가 있는데 이 작업을 injection이라고 하며
되도록 이렇게 인스턴스 속성을 만들라고 합니다




4. 클래스가 인스턴스 없이 호출할 수 있는 메서드 -static method, class method
1)static 매서드
=>self없이 클래스 안에 만들 수 있는 메서드
-> 이 메서드는 클래스기 인스턴스 없이 호출할 수 있고 인스턴스를 이용해서 호출 가능
=> 만드는 방법
@staticmethod
def 이름(self을 제외한 매개변수):
내용
=>파이썬에서 @로 시작하는 단어는 decorator라고 하느데 코드를 하나의 단어로 작성하고자 할때 사용

이코드는 메서드의 내용이 수행되기 전이나 수행된 에 하고자 하는 작업에 대한 코드(Filter,AoP)

 

 

5.inheritance(상속)

1)기본적인  개념

=>상속:하위 클래스가 상위 클래스의 모든 것을 물려받는 것

=>상속이란 표현 대신에 is a 라는 표현을 사용하기도 합니다

=> 기본적으로 상속을 구현을 할 때는 여러 개의 클래스를 만들어서 사용하다가 클래스들에 공통된 내용이 있는 경우 공통된 내용을 여러 번 작성하기 싫어서 공통된 내용을 상위 클래스에 만들고 상속을 받는 방법으로 대체합니다.

=> 프로그램을 여러개 만들다보면 공통적으로 사용하는 기능이 존재할 수 있습니다. 이경우에는 이러한 공통된 기능을 미리 만들어서 제공하기도 합니다
이 경우에는 클래스의 기능을 부족할 때 확장하기 위해서 상속을 합니다.
이 경우가 프레임워크를 사용하는 경우입니다.
=>단일 상속과 다중상속
단일 상속은 하나의 클래스로 부터 상속 받는 것이고 다중 상속은 여러 개의 클래스로부터 상속을 받는 것
파이썬은 다중 상속을 지원
파이썬에서 다중 상속을 구현 할때 주의해야 할 점은 상위 클래스 이름의 순서입니다.
다중 상속을 할때 문제가 생기는게 클래스 내에서 같은 함수명을 쓸때 불러오는 순서는 먼저온 순서를 활용합니다.

=>상속의 목적
여러 클래스의 공통된 내용이 존재해서- 일반 프로그래밍
제공되는 클래스의 기능이 부족해서- 프레임워크를 사용하는 경우
공통된 인터페이스를 사용하기 위해서- 다형성을 구현

 

2)상속구현

class 클래스이름(상위클래스 이름 나열(여러개일수도 있음) ): 

class Phone:
  def superMethod(self):
    print("상위 클래스 메서드")
    
    
class Camera:
  def superMethod(self):
    print("Camera 클래스의 메서드")

#상속받은 하위클래스    
class SmartPhone(Phone,Camera):
  def subMethod(self):
    print("smartPhone 클래서의 메서드")
    
subObj=SmartPhone()
subObj.subMethod()
#Smartphone 클래스는 Phone 클래스를 상속받았으므로 Phone클래스의 멤버를 사용가능
subObj.superMethod()

 

4)상위 클래스의 __init__ 호출
=> 파이썬에서는 하위 클래스의 __init__메서드에서 상위 클래스의 __init__를 자동으로 호출하지 않습니다.
대다수의 객체 지향 언어에서 상속을 받으면 하위 클래스의 생성자에서 상위 클래스의 생성자를 자동으로 호출합니다
하위 클래스의 __init__ 안에서 상위 클래스의 초기화 메서드를 호출하고자 하는 경우는 super().__init__()을 호출해야합니다.

class Phone:
  def __init__(self):
    self.name="전화기"
    
    
  def superMethod(self):
    print("상위 클래스 메서드")
    

class SmartPhone(Phone,Camera):
  
  def __init__(self):
    #print(self.name) #no attribute라고 오류남
    #파이썬은 상위 클래스의 init을 자동으로 호출하지 않음
    #상위 클래스의 init을 호출하지 않고, 상위 클랫으의 소성을 사용하면 에러
    #상위 클래스의 __init__호출
    super().__init__() #이를 활용하면 오류가 나지 않음
    
    print(self.name)
    
    
 subObj=SmartPhone()
subObj.subMethod()
#Smartphone 클래스는 Phone 클래스를 상속받았으므로 Phone클래스의 멤버를 사용가능
subObj.superMethod()

 

5)Method Overriding
=>method overloading(중복 정의): 하나의 클래스에 동일한 이름이지만 매개변수의 개수나 자료형이 다르게 만들어진 메서드가 존재하는 경우

=>method overriding(재정의):상위 클래스에 존재하는 메서드(내용이 있는 메서드)를 하위 클래스에서 다시 정의 하는것
★목적은 기능 확장 ★
언어에서는 상위 클랫의 메서드를 호출하지 않는 것이 에러가 아니지만 프레임워크에서는 상위 클래스의 메서드를 호출하지 않으면 에러가 발생합니다.
기능이 다르면 다른 이름을 사용하는게 맞음

 

class Camera:
  def superMethod(self):
    print("Camera 클래스의 메서드")
    
    
class SmartPhone(Camera):
	  #상위 클래스에 존재하는 메서드를 하위 클래스에서 다시 구현
  #Method Overriding
  def superMethod(self):
    super().superMethod()
    print("Smartphone 클래스의 메서드")
    
      
subObj=SmartPhone()
subObj.superMethod()

 

6) Abstract(추상)
=>Abstract Class(추상 클래스)                                                                                                                                                                            
인스턴스를 만들수 없는 클래스
상속을 통해서만 사용하는 클래스
추상 클래스를 만드는 방법
import abc
class 클래스이름(metaclass=abc.ABCMeta)

=>import는 파이썬 기본 모듈이 아닌 파일의 내용을 현재 프로그램에 가져올때 사용하는 명령어
import abc는 abc.py라는 파일의 내용을 abc라는 이름으로 묶어서 가져오는 것
import abc as X:abc.py라는 파일의 내용을 X라는 이름으로 묶어서 가져오는 것

=>abstract method(추상 메서드)
내용이 없는 메서드. 하위 클래스에서 반드시 구현해야 하는 메서드 
반드시 추상클래스에 존재
생성 방법
@abc.abstractmethod
def 이름(매개변수):
pass

=>추상을 사용하는 이유
동일한 인터페이스를 제공하기 위해서 & 테스트 주도개발

목적? 메뉴판을 기억해라.음식점에갔어. 뭐뭐를 해준다할때 주방가서 음식 보는게 아니라, 메뉴판을 봄.
메뉴판에는 실제 내용물은 없지만 그건 음식점에서 반드시 해줘야함.이 음식점이 어떤 음식을 하는지 모르니깐 메뉴판으로 소통.

#추상 클래스를 만들기 위한 모듈
import abc
class Phone(metaclass=(abc.ABCMeta)):
  
  @abc.abstractmethod
  def call(self):
    pass

# 추상 클래스를 상속받은 클래스
#추상 메서드를 반드시 구현
class SmartPhone(Phone):
  def call(self):
    print("메서드")
    
smartphone=SmartPhone()

 

7)템플릿

추상 메서드를 소유한 추상 클래스(인터페이스, 프로토콜)를 만들고 이를 구현한 클래스를 만들어서 사용하는 방식

=>고객의 요구
데이터를 추가하는 기능

=>고객의 요구에 해당하는 템플릿 생성

import abc

class InsertService(metaclass=abc.ABCMeta):
  #추상 메서드
  @abc.abstractmethod
  def insert(self,data)->bool:
    pass
  
class InsertServiceImpl(InsertService):
  #대략적인 동작하는 코드를 작성하고 테스트 한후 실제 코드를 구현하는 방식
  def insert(self,data)->bool:
    print("데이터 추가")
    return True
  
service=InsertServiceImpl()
print(service.insert("데이터"))


8)polymorphism(다형성)
=>동일한 메세지에 대하여 다르게 반응하는 성질
하나의 코드가 호출하는 인스턴스에 따라 다른 메서드를 호출하는 것
상속과 오버라이딩을 이용해 구현

import abc
class starcraft(metaclass=abc.ABCMeta):
  #추상메서드
  @abc.abstractmethod
  def attack(self,data)->None:
    pass

class Protoss(starcraft):
  def attack(self,data)->None:
    print("프로토스",data)
    
class Terran(starcraft):
  def attack(self,data)->None:
    print("테란",data)
       
star=Protoss()
star.attack("드라군")
star=Terran()
star.attack("종이 비행기")

 

 

 

'Study > PYTHON,Django' 카테고리의 다른 글

Django(2)-데이터베이스 연동  (0) 2024.01.25
Django(1)-웹 프로그래밍 기초  (0) 2024.01.24
PYTHON(3)-객체지향(OOP)  (0) 2024.01.09
Python(2)-모듈,패키지  (0) 2024.01.05
Python(1)-Python 기초  (0) 2024.01.02