- 는 개념 정리
- 는 개인적으로 새롭게 알게 된 점
8-1. 클래스의 기본
객체 지향 프로그래밍 (Object Oriented Programming)
- 객체를 우선으로 생각해서 프로그래밍 한다는 의미.
- 프로그래밍에서 필요한 데이터를 추상화시켜, 상태와 행위를 가진 객체를 만들고, 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 언어.
객체 (Object) & 추상화 (abstraction)
- 객체: real world의 대상(object)을 소프트웨어 세계에 구현할 대상.
- e.g. 사람이라는 현실의 객체를 소프트웨어 세계에 구현하였을 때, 소프트웨어 세계에 구현된 '사람'이 객체인 것.
- (책에서 정의한 바) 여러 가지 속성을 가질 수 있는 대상.
- 추가적으로, real world 대상을 소프트웨어 세계에 구현할 때, 모든 데이터를 표현할 수는 없음. 따라서 프로그램에서 필요한 요소만을 사용해서 객체를 표현하는 것을 추상화 (abstraction) 라고 함.
- 즉, 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것을 추상화 라고 함.
클래스 (Class)
- 객체를 구현하기 위한 설계도
- 클래스는 CamelCase 규칙을 따름.
인스턴스 (Instance)
- 이 설계도(Class)에 따라서 소프트웨어 세계에 구현된 실체
- 설계도를 바탕으로 객체를 소프트웨어에 실체화 하면, 그것이 인스턴스이고, 이 과정을 인스턴스화 (instantiation) 라고 함.
- 실체화된 인스턴스는 메모리에 할당 됨.
+추가) 가끔 객체와 인스턴스를 혼용해서 사용하여, 클래스 생성에 따라 메모리에 할당된 객체인 인스턴스를 '객체'라고 부르는데, 틀린 말은 아님. 인스턴스라고 부르는게 더 정확하지만, 개념적으로 인스턴스는 객체에 포함된다고 볼 수 있기 때문.
생성자 (Constructor) & 메소드 (Method)
메소드 (Method)
- 클래스가 가지고 있는 함수.
- 인스턴스와 관계되는 일을 하는 함수.
- 인스턴스에서 메소드를 호출하기 위해서 . 연산자를 이용함.
생성자 (Constructor)
- 인스턴스 생성 시에 자동으로 호출됨.
- (책 내용) 클래스 이름과 같은 함수, 즉 클래스 이름과 같은 인스턴스를 생성할 때 만드는 함수.
- 클래스 내부에 __init__ 라는 함수를 만들어, 객체를 생성할 때 처리할 내용을 작성할 수 있음.
8-2. 클래스의 추가적인 구문
클래스를 사용하는 것은 작정하고 속성과 기능을 가진 객체를 만들겠다는 의미. 그래서 파이썬은 그에 따른 부가적인 기능을 지원함.
isinstance()
- 객체(인스턴스)가 어떤 클래스로부터 만들어졌는지 확인할 수 있도록 하는 함수.
- isinstance() 함수는 첫 번째 매개변수에 객체(인스턴스), 두 번재 매개변수에 클래스를 입력함.
isinstance(인스턴스, 클래스)
- 인스턴스가 해당 클래스를 기반으로 만들어졌다면 True, 전혀 상관이 없는 인스턴스와 클래스라면 False 리턴.
- 단순한 인스턴스 확인이라면 type() 함수를 사용할 수도 있음.
- isinstance() 함수와 type() 함수로 확인하는 것의 차이
- isinstance() 함수는 상속 관계까지 확인함.
- type() 함수는 상속 관계를 확인하지 않음.
- isinstance() 함수를 사용하면, 이처럼 하나의 리스트로도 여러 종류의 데이터를 다룰 수 있음.
특수한 이름의 메소드
__method__는 특수한 경우에 자동적으로 호출되는 함수라고 생각하면 됨.
__init__ 메소드와 __str__ 메소드는 특별한 메소드. 객체를 문자열로 표현한 것을 반환함.
__init__ 메소드
- 객체 인스턴스화를 쉽게 해주는 __init__ 메소드.
- 클래스 생성시 자동으로 실행되는 메소드.
+추가) __del__
- 객체가 소멸할 때 자동으로 실행되는 메소드
__str__ 메소드
- 디버깅할 때 유용한 __str__ 메소드.
- 객체를 출력하면 파이썬은 __str__ 메서드를 호출함.
- 즉, 클래스 자체의 내용을 출력하고 싶을 때, 형식을 지정하는 메소드.
- 책에서는 str() 함수를 호출할 때 __str__() 함수가 자동으로 호출된다고 설명함.
- str() 함수를 호출할 때 뿐만 아니라, print() 함수 등을 사용해서 클래스 자체의 내용을 출력할 때도 __str__ 메소드가 사용됨.
__init__, __str__ 메소드 외의 다른 함수들.
이름 | 영어 | 설명 | 연산자 |
eq | equal | 같다 | == |
ne | not equal | 다르다 | != |
gt | greater than | 크다 | > |
ge | greater than or equal | 크거나 같다 | >= |
lt | less than | 작다 | < |
le | less than or equal | 작거나 같다 | <= |
- 비교 연산자 사용 시 자동으로 호출되는 메소드.
- return 으로 True, False를 반환함.
클래스 변수와 메소드
인스턴스가 속성(변수)과 기능(함수)을 가질 수 있듯이,
클래스도 속성(변수)와 기능(함수)를 가질 수 있음.
클래스 변수 & 인스턴스 변수
클래스 변수
- 메서드 밖에 존재하는 변수. 이는 해당 클래스를 사용하는 모두에게 공용으로 사용되는 변수.
- 클래스 변수는 class 구문 바로 아래의 단계에 변수를 선언하면 됨.
#클래스 변수 만들기
class Student:
value = 0
#클래스 변수에 접근
Student.value
- 클래스 변수에 접근하기 위해서, 클래스 이름.변수 이름 사용.
- 클래스 내부와 외부에서 클래스 변수에 접근할 때는 모두 (클래스 이름.변수 이름) 의 형태로 접근함.
+추가) 인스턴스 변수
self가 붙어 있는 변수는 인스턴스 변수.
- 클래스 변수는 클래스의 네임스페이스에 위치하며, 인스턴스 변수는 인스턴스의 네임스페이스에 위치함.
클래스와 인스터스 비교 설명 GOOD
위키독스
온라인 책을 제작 공유하는 플랫폼 서비스
wikidocs.net
클래스 함수
* 파이썬에서는 클래스에서 직접 접근할 수 있는 메소드가 세 가지 있음. *
- +추가) instance method (인스턴스 메서드)
- +추가) static method (정적 메서드)
- class method (클래스 메서드-> 책에서 말하는 클래스 함수가 classmethod)
1. 인스턴스 메서드
- 가장 흔히 쓰이는 인스턴스 메서드는 인스턴스 변수에 접근 할 수 있도록, 메서드의 첫 번째 파라미터에 항상 객체 자신을 의미하는 'self' 파라미터를 가짐. 인스턴스 메서드는 여러 파라미터를 가질 수 있지만, 첫 번째 파라미터는 항상 self를 가짐.
- 해당 메서드는 호출한 객체에만 영향을 미침.
- 객체 속성에 접근이 가능함.
- 호출 방법
- 해당 클래스 안에서는 self.메서드명
- 클래스 밖에서는 객체.메서드명
class Test:
def __init__(self, name, age):
self.name = name
self.age = age
def print_info(self):
print(self.name, ',', self.age) #1
def test_func(self):
self.print_info()
test1 = Test('hong', 22)
test1.print_info() #2 결과값 : hong , 22
test1.test_func() #3 결과값 : hong , 22
2. 정적 메서드
- 인스턴스를 생성하지 않고도 호출하는 메서드.
- 객체와 독립적이지만, 로직상 클래스 내에 포함되는 메서드.
- self 파라미터를 가지고 있지 않음. 따라서 인스변스 변수에 액세스가 불가능.
- 그러나, 정적 메서드 내부에서 클래스 변수에는 클래스명.클래스 속성명 으로 액세스가 가능함.
- 클래스에서 직접 접근할 수 있는 메소드. 파이썬에서는 다른 언어와는 다르게 정적메소드임에도 불구하고, 인스턴스에서도 접근이 가능함. 정적 메서드는 특별히 추가되는 인자가 없음.
- @staticmethod라는 데코레이터를 붙여서 해당 메서드가 정적 메서드임을 표시함.
class Calc:
count = 10 # 클래스 변수(클래스 속성)
@staticmethod
def add(a):
print(a + Calc.count) # 클래스 속성에는 엑세스가 가능하다.
@staticmethod
def mul(a):
print(a * Calc.count)
Calc.add(15) # 결과값 :25
Calc.mul(15) # 결과값 : 150
class StringUtils:
@staticmethod
def toCamelcase(text):
words = iter(text.split("_"))
return next(words) + "".join(i.title() for i in words)
@staticmethod
def toSnakecase(text):
letters = ["_" + i.lower() if i.isupper() else i for i in text]
return "".join(letters).lstrip("_")
- 정적 메서드는 유틸리티 메서드를 구현할 때 많이 사용됨.
- e.g. StringUtils 클래스는 2개의 정적 메서드로 이뤄짐. toCamelCase 메서드는 snake_case 문자열을 CamelCase 로 변환, toSnakecase는 그 역방향으로 변환. 이 두 개의 메서드는 매개 변수로 넘어온 문자열에만 의존하는 순수한 (pure) 함수이기 때문에 굳이 클래스의 이루로 선언할 필요는 없지만, 이렇게 비슷한 류의 여러 유틸리티 메서드를 하나의 클래스로 묶어두고 싶을 때 정적 메서드로 선언.
3. 클래스 메서드
- 클래스 메서드는 첫 번째 인자로 클래스(cls) 를 입력함.
- 첫번째 매개변수로 클래스 인스턴스가 아닌, 클래스 자체가 넘어오는 것.
- 클래스 메서드는 이 cls를 통해 클래스 속성 (attribute)에 접근하거나, 클래스 메서드 호출.
- 그러나 인스턴스 메서드와 달리 인스턴스 속성에 접근하거나 다른 인스턴스 메서드를 호출 하는 것은 불가능 (self 가 없으니까)
- 인스턴스 없이 호출이 가능하다는 점에서 정적 메서드와 비슷하지만, cls인자가 추가된다는 점에서 차이점이 있음.
- cls
- e.g. hello 클래스의 num 속성에 접근하기 위해서는?
#staticmethod
class hello:
num = 10
@staticmethod
def calc(x):
return x + 10 + hello.num
print(hello.calc(10))
#결과
30
- 정적 메서드: 객체로 접근하는 것이 아니기 때문에, self.num을 사용할 수 없음. 따라서 hello.num 의 정적 변수로 접근함.
#classmethod
class hello:
num = 10
@classmethod
def calc(cls, x):
return x + 10 + cls.num
print(hello.calc(10))
#결과
30
- 클래스 메서드: cls로, 클래스의 어떤 속성에도 접근할 수 있음. 이 경우 cls.num을 통해 hello 클래스의 num 속성에 접근함.
+추가) 상속 관계가 있는 클래스들에서는 cls가 가리키는 클래스는 상속 받은 클래스임.
class hello:
t = '내가 상속해 줬어'
@classmethod
def calc(cls):
return cls.t
class hello_2(hello):
t = '나는 상속 받았어'
print(hello_2.calc())
#결과
나는 상속 받았어
좀 더 알아보기
1. 가비지 컬렉터
2. 프라이빗 변수와 게터/세터
3. 상속
가비지 컬렉터
- 컴퓨터가 일을 할 때, 처리할 정보들을 공간이 필요함. 공간 = 메모리.
- 코드를 작성하고, 프로그램을 실행하면서 데이터(변수, 함수, 객체 등)가 메모리에 올라가고, 메모리가 가득 차는 것을 방지할 필요가 있음. => 더 이상 사용할 가능성이 없는 데이터를 메모리에서 제거하는 역할: 가비지 컬렉터.
- 메모리를 비우지 못해서 발생하는 문제를 '메모리 누수', 'memory leak'이라고 함.
- C/C++ 언어에서는 데이터를 메모리에서 제거하는 코드를 직접 작성해야 했는데, 자바를 비롯한 새로운 언어에서 가비지 컬렉터 도입.
- 메모리를 알아서 관리하는 언어 = managed language <-> unmanaged language
- 가비지 컬렉터 작동 방식
- mark-and-sweep: 아직 필요한 것들만 마크한 다음에 마크 안 된 것들은 갖다버리는 방식.
- 프로그래밍 측면에서, 루트에서 닿지 않는 변수들을 치우는 것.
- reference counting (참조 카운팅): 한 요소가 다른 요소에게 몇 번 참조되는지 세어서, 그 수가 0이 되면 치우는 것.
- mark-and-sweep: 아직 필요한 것들만 마크한 다음에 마크 안 된 것들은 갖다버리는 방식.
- 메모리 누수를 방지하는 방식은 언어의 특성마다 다름. 따라서 사용하는 언어나 플랫폼 등에 따라 바람직한 메모리 관리 방식을 찾아볼 필요가 있음.
프라이빗 변수와 게터/세터
private(비공개) & pulbic(공개)
private 멤버: 클래스 안에서만 접근가능한 멤버
public 멤버: 클래스 안과 밖에서 모두 접근가능한 멤버
- 메서드에서도 public, private 속성 적용이 가능함.
public을 사용할 때: _ _변수명_ _
private을 사용할 때: _ _변수명
- 사실 정확하게 말하면, 파이썬에는 public과 private 이란 개념이 없지만, 이와 같이 변수의 이름을 가지고 그것과 비슷한 기능을 표현할 수 있음.
- cTest 객체에는 __test_var라는 변수가 없다고 함, 이와 같이 private 과 비슷한 효과를 볼 수 있음.
(책 내용) 파이썬은 클래스 내부의 변수를 외부에서 사용하는 것을 막고 싶을 때, 인스턴스 변수 이름을 __변수이름 형태로 선언(언더바 2개).
=> private 변수에 접근하고 싶을 때, getter & setter 사용.
getter & setter (데코레이터)
파이썬 클래스에서 메서드를 통하여 속성의 값을 가져오거나, 저장하는 경우가 있음. 이 때 값을 가져오는 메서드를 getter, 값을 저장하는 메서드를 setter라고 함.
CODE 1
def __init__(self):
self.__age = 0
def get_age(self): # getter
return self.__age
def set_age(self, value): # setter
self.__age = value
james = Person()
james.set_age(20)
print(james.get_age())
OUTPUT 1
20
CODE 2 (getter, setter)
class Person:
def __init__(self):
self.__age = 0
@property
def age(self): # getter
return self.__age
@age.setter
def age(self, value): # setter
self.__age = value
james = Person()
james.age = 20 # 인스턴스.속성 형식으로 접근하여 값 저장
print(james.age) # 인스턴스.속성 형식으로 값을 가져옴
OUTPUT 2
20
- getter와 setter 메서드의 이름은 모두 age. 또한 getter에는 @property가 붙어있고, setter에는 @age.setter가 붙어있음. 즉, 값을 가져오는 메서드에는 @property 데코레이터를 붙이고, 값을 저장하는 메서드에는 @메서드이름.setter 데코레이터를 붙임.
- @property와 @age.setter를 붙이면, james.age 처럼 메서드를 속성처럼 사용할 수 있음. 값을 저장할 때, 메서드에 바로 값을 할당하면 되고, 값을 가져올 때도 메서드에 바로 접근하면 됨.
상속 (inheritance) & super()
- 프로그래밍 언어는 기반이 되는 것은 부모 (parent)라고 부르고, 이를 기반으로 생성한 것을 자식 (child)라고 부름. 부모가 자식에게 자신의 기반을 물려주는 기능을 '상속'이라고 함.
- 클래스의 상속 기능을 사용하면, 부모 클래스에서 만들어둔 기능(메서드)과 속성(변수)을 물려받을 수 있음.
- (책 내용) 상속은 기존에 있는 클래스를 기반으로 조금 수정해서, 내가 원하는 클래스를 만들 때 사용.
- 부모에 정의되어 있는 함수를 자식에서 다시 정의하는 것을 재정의, 오버라이드 (override) 라고 함.
super()
- 부모 클래스의 이름을 알고 있을 경우 Person.__init__과 같이 부모 클래스의 이름과 . 을 사용하여 부모클래스의 메소드를 호출 할 수 있음.
- super() 를 통해 부모 클래스의 메소드를 손쉽게 이용할 수 있음.
- 부모 클래스를 명시적으로 적어줄 필요가 없으므로 프로그램의 유지 보수가 쉬움.
- super() 에서는 self를 사용할 필요가 없음.
- 실행 기능을 똑같음.
끝.
'Python Basic > 혼공파' 카테고리의 다른 글
나머지 공부 (0) | 2021.01.26 |
---|---|
[혼공파] Chapter 07 모듈 (0) | 2021.01.20 |
[혼공파] Chapter 06 예외 처리 (0) | 2021.01.13 |
[혼공파] Chapter 05 ③함수 고급 (0) | 2021.01.12 |
[혼공파] Chapter 05 ②함수의 활용 (0) | 2021.01.12 |