Python

05.OOP(1)

seunghyeoniya 2023. 8. 17. 08:30

-------------------------

05.OOP

-------------------------

 

//

 

OOP와 AOP의 특징 : https://greendreamtrre.tistory.com/601

 

OOP(Object Oriented Programming, 객체지향 프로그래밍) : 모든 데이터를 현실에 빗대어 객체로 다루는 프로그래밍 기법이다.

객체지향 언어의 5가지 특징은 다음과 같다.

1. 캡슐화 (Encapsulation) : 데이터와 함수를 하나로 묶는다.

2. 정보은닉 (Information Hiding) : private로 선언한 데이터는 자기 자신을 통해서만 접근(setter, getter)이 가능하다.

3. 추상화 (Abstraction) : 불필요한 부분은 생략하고 중요한 것에만 초점을 맞춰 모델로 만든다.

4. 상속성 (Inheritance) : 상위 클래스에 정의된 모든 것을 하위 클래스가 물려받는다.

5. 다형성 (Polymorphism) : 호출하는 객체에 따라 다른 동작을 한다.

 

AOP(Aspect Oriented Programming, 관점지향 프로그래밍) : OOP를 더욱 발전시키기 위한 개념이다.

하나의 소프트웨어가 하나의 거대한 OOP로써 설계, 프로그래밍 되었다면 이것을 각 기능별로 모듈화 해서 분리를 시키는 개념이다.

 

//

 

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

1. 개요

1) 3대 특징

=> Encapsulation(캡슐화)

불필요한 정보는 숨기고 중요한 정보만을 표현해서 프로그램을 간단하게 만드는 것

(인터페이스를 간단하게 만드는 것)

=> Inheritance(상속성)

하위 클래스가 상위 클래스의 모든 요소를 물려받는 것

=> Polymorphism(다형성)

동일한 메세지에 대하여 다르게 반응하는 성질

 

2) 용어

=> Object(객체) : 프로그램에 사용되는 모든 것

 

=> Class : 사용자 정의 자료형

동일한 목적을 달성하기 위해 모인 속성(데이터)과 메서드(기능 - 함수)의 집합

정적(static): 한번 만들면 변경되지 않는

 

-> 일반적으로 클래스 이름을 대문자로 시작하고 변경할 생각이 없는 데이터의 이름은 모두 대문자로 만드는 것이 관례이다.

 

=> Instance : Class를 기반으로 메모리 할당을 받은 객체

동적(dynamic): 변경 가능한

 

=> Class Object : Class를 의미

 

=> 정적바인딩과 동적바인딩

정적바인딩은 실행 전에 결정되는 것 - 변수를 만들 때 자료형을 명시적으로 작성하거나 암묵적으로 결정해두고 사용하기 때문에 실행 중에 변수에 다른 종류의 데이터를 삽입할 수 없음

 

동적바인딩은 실행 중 결정 가능한 것 - 참조형 데이터만 존재하고 변수는 데이터의 참조를 저장하기 때문에 실행중에도 다른 종류의 데이터를 대입할 수 있음.

 

-> 정적바인딩은 준비를 해놓고 시작하기 때문에 속도가 빠르고 컴파일 오류의 가능성이 줄어든다.

 

=> 속성(attribute) : Instance를 구성하는 데이터

 

=> method : Class 안에 만들어진 기능(함수)

 

=> property : 속성처럼 사용하는데 실제로는 method를 호출하는 것

 

=> record나 sturcture(구조체) : 하나의 행을 의미, Instance를 구성하는 속성의 집합

 

=> python의 모든 데이터는 기본적으로 instance

 

=> Information Hiding(정보 은닉) :불필요한 부분을 숨기는 것

 

2. Class 와 Instance

1) 클래스 생성

class 클래스이름:

초기화 메서드 생성

 

메서드 생성

 

2) 인스턴스 생성 (인스턴스 : 속성과 클래스에 대한 참조)

=> 인스턴스 이름 = 초기화 메서드(매개변수) -> 초기화 메서드의 이름은 클래스 이름

=> 인스턴스를 생성하는 메서드를 호출하면 인스턴스를 생성하고 그 참조를 리턴

 

3) 인스턴스나 클래스를 이용한 멤버 호출

인스턴스나 클래스.속성

인스턴스나 클래스.메서드(매개변수)

 

4) Method

=> 인스턴스가 있어야만 호출되는 메서드와 인스턴스가 없어도 호출되는 메서드(static, class)로 구분

=> 인스턴스가 있어야 하는 메서드 생성

def 메서드이름(인스턴스 참조를 저장할 매개변수, [매개변수 나열]):

내용

 

관례상 인스턴스 참조를 저장할 매개변수의 이름은 self

 

=> 인스턴스가 있어야 하는 메서드 호출

클래스이름.메서드이름(인스턴스이름, 매개변수) : Unbound 호출

 

인스턴스이름.메서드이름(매개변수) : Bound 호출

 

클래스 내부의 다른 메서드에서 호출 : self.메서드이름(매개변수)

 

1), 2), 3), 4)의 ex.

# 클래스 생성

# class 클래스이름:

class Student:

# 인스턴스가 있어야만 호출되는 메서드 생성

# def 메서드이름(self, 매개변수): # 첫 번째 매개변수인 인스턴스 참조를 저장할 매개변수의 이름은 self를 주로 사용한다.

def disp(self):

print("인스턴스 생성")

 

# 인스턴스 생성

# 인스턴스 이름 = 클래스 이름(매개변수)

student = Student()

# -> 여러 번 사용할 때 편리하게 쓰기 위해서 Bound 호출을 선택하였다.

# -> 한 번만 사용하는 것이라면 Bound 호출이 아니라, Unbound 호출을 이용해 클래스를 곧바로 써도 된다.

 

 

# 메서드 호출 - bound 호출

student.disp()

# 메서드 호출 - Unbound 호출

Student.disp(student)

 

5) 인스턴스의 속성 만들기

=> 파이썬에서 인스턴스의 속성을 만들고자 하는 경우에는 인스턴스가 있어야 호출되는 메서드 안에서 self.속성명으로 데이터를 대입하면 만들어집니다.

메서드 안에서 self.을 이용하지 않고 만든 속성은 지역 변수가 됩니다.

=> 클래스 외부에서 "인스턴스.속성이름 = 데이터"를 작성하면, 속성이 존재할 때 속성의 값을 변경하는 것이고 속성이 존재하지 않으면 속성이 생성됩니다.

class Student:

def setName(self, name):

self.name = name # 지역 변수가 아니라 인스턴스의 속성을 생성

# 인스턴스 생성

stu = Student()

stu.setName("파이터")

print(stu.name)

 

stu.score = 94 # 인스턴스에 score라는 속성이 있으면 수정, 없으면 생성

print(stu.score)

 

6) Class 속성

=> class 내부 그리고 method 외부에 변수를 생성해서 데이터를 대입하면 class 속성이 됩니다.

=> class의 속성은 클래스와 인스턴스 모두 접근이 가능합니다.

인스턴스를 이용해서 접근할 때 그 속성이 인스턴스 내부에 없으면 class 속성을 호출하지만 인스턴스 내부에 존재하면 인스턴스의 속성을 호출합니다.

즉 대입문을 이용하면 인스턴스의 속성을 생성해서 사용합니다.

클래스 속성은 인스턴스를 이용해서 접근하는 것을 권장하지 않습니다.

class Student:

class_data = "클래스의 속성"

 

student = Student() # 인스턴스를 생성할 때는 이처럼 클래스이름을 호출한다.

print(Student.class_data) # 클래스이름을 이용해서 클래스 속성에 접근

print(student.class_data) # 인스턴스이름을 이용해서 클래스 속성에 접근

 

Student.class_data = "클래스 데이터 수정" # 클래스이름으로 클래스 속성 수정

print(Student.class_data) # 클래스이름을 이용해서 클래스 속성에 접근

print(student.class_data) # 인스턴스이름을 이용해서 클래스 속성에 접근

 

student.class_data = "인스턴스를 이용해서 클래스 데이터 수정" # 인스턴스이름으로 클래스 속성 수정

print(Student.class_data) # 클래스 이름을 이용해서 클래스 속성에 접근

print(student.class_data) # 인스턴스 이름을 이용해서 클래스 속성에 접근

# -> 클래스(Student)에는 class_data라는 속성이 존재하지만, 인스턴스(student)에는 존재하지 않아서 새로 생성된다. 따라서 출력 결과가 다르게 나타난다.

 

***** 정리

-> 똑같은 속성으로 이루어진 것들을 Class로 만들고 그 안에서 똑같지 않은, 다른 것들을 Instance로 구분한다.

클래스에서 만든 속성은 클래스나 인스턴스 모두로 접근할 수는 있지만, 일반적으로 클래스에서 접근하는 것이 더 좋다. (파이썬에서만 가능하다.)

인스턴스로 접근하는 것은 상당히 비효율적이다. (데이터가 존재하지 않으면 한 바퀴 돈다.)

-> 클래스는 첫 글자를 대문자로 인스턴스는 첫 글자를 소문자로

-> Java나 C++은 인스턴스 참조를 저장할 매개변수로 self 대신에 this를 사용한다.

-> 속성은 각자 가지고 있지만 메서드는 공유합니다.

-> 클래스는 바로 줄 수 없으므로 인스턴스로 만들어야 한다.

인스턴스를 이용하면 생성하지 않은 것도 만들 수 있다.

 

깨알) 1, 2, 3과 같은 숫자는 int 클래스에 속하고, x = 1이라 하면, int 클래스를 통해 x라는 인스턴스를 생성하는 것이다.

 

7) is 연산자

=> python의 변수는 데이터를 저장하고 그 데이터의 id를 저장하는 개념

=> == 연산자는 목적이 id를 비교하는 것이 아닙니다.

파이썬에서 == 연산자는 내부에 만든 __eq__ 메서드를 호출해서 그 결과를 리턴하는 연산자입니다.

== 연산자는 오버로딩(기능을 변경)이 가능하기 때문에 어떻게 동작할지 예측하기 어렵습니다.

 

=> id를 비교하는 연산자는 is 연산자 입니다.

is 연산자는 오버로딩이 안되기 때문에 명확하게 id를 비교한다고 할 수 있습니다.

class Student:

class_data = "클래스의 속성"

# 인스턴스를 생성해서 대입

stu1 = Student()

# 인스턴스를 생성해서 대입

stu2 = Student()

# stu1의 데이터를 대입 : stu1이 참조하고 있는 데이터의 참조를 stu3가 참조합니다.

stu3 = stu1

 

# 2개의 인스턴스가 동일한지 여부를 확인

print(stu1 == stu2) # 내부의 데이터가 같은지 확인

print(stu1 is stu2) # id가 같은지 확인

# -> 인스턴스는 속성이나 클래스에 대한 참조를 가져오는 것이기 때문에,

# stu1과 stu2는 서로 다른 인스턴스로 각각 다른 참조를 나타내기(가리키기) 떄문에 위의 두 결과에 대해서 False가 나오게 된다.

 

print(stu1 == stu3) # 내부의 데이터가 같은지 확인

print(stu1 is stu3) # id가 같은지 확인

# -> stu3은 stu1의 참조를 그대로 받아오므로 위의 두 결과에 대해서 True가 나오게 된다.

 

8) Accessor - 접근자 메서드

=> 객체지향 언어에서는 인스턴스를 가지고 속성에 직접 접근하는 것을 권장하지 않습니다.

=> 속성에 접근하는 메서드를 이용해서 속성의 값을 가져다가 사용하고 수정하도록 합니다.

속성의 값을 리턴하는 메서드를 getter라고 하고 속성의 값을 수정하는 메서드를 setter라고 합니다.

 

=>getter

이름은 get속성이름으로 하고 매개변수는 일반적으로 없고 속성을 리턴하기만 합니다.

속성의 자료형이 bool인 경우 get 대신에 is를 붙입니다.

속성의 이름의 첫글자는 대문자로 표기하는데 파이썬에서는 대문자 대신에 _를 사용하는 경우가 있습니다.

 

=>setter

이름은 set속성이름으로 하고 매개변수는 속성과 동일한 자료형의 데이터 1개로 생성

내용은 매개변수로 받은 데이터를 속성에 대입합니다.

 

=> 속성의 자료형이 Sequence(list)인 경우

인덱스를 받아서 인덱스 번째 데이터를 리턴하는 getter를 추가로 생성하고 인덱스와 데이터 1개를 받아서 인덱스 번째 데이터를 수정하는 setter를 생성하기도 합니다.

# 이름과 점수를 갖는 객체를 여러개 필요로 하는 경우

class Student:

def getName(self):

return self.name

def setName(self, name):

self.name = name

def getScore(self):

return self.score

def setScore(self, score):

self.sore=score

 

stu1 = Student()

# setter를 이용한 속성 생성과 설정

stu1.setName("반승현")

stu1.setScore(99)

# getter를 이용한 속성 사용

print(stu1.getName())

print(stu1.getScore())

# 최근에 등장한 IDE는 대부분 getter와 setter를 만드는 유틸을 제공합니다.

 

//

 

1. 클래스를 부여하면 인스턴스를 생성할 수 있어야 하고,

2. 메서드도 호출할 수 있어야 한다.

 

#python

'Python' 카테고리의 다른 글

05.OOP(2)  (0) 2023.08.17
04.Function(2)  (0) 2023.08.16
04.Function(1)  (0) 2023.08.05
03.Control Statement  (0) 2023.08.05
02.Variable_Operator  (0) 2023.08.05