데이터를 표현하는 속성(attribute)와 행위를 표현하는 메서드(method)를 포함하는 논리적인 컨테이너
객체
컴퓨터 시스템에서 다양한 기능을 수행하도록 속성과 메소드를 가진 요소
type() : 객체의 자료형을 반환
id() : 객체의 id를 반환
n + 100 == n.__add__(100)
: n 객체와 정수 100의 합을 연산한다.
클래스의 개념
class 클래스명
# 이 부분에 관련 코드 구현
속성 (변수) : 클래스/인스턴스 변수 (attribute)
기능 (클래스 안에서 구현된 함수) : 메서드(method)
class Car:
# 자동차의 필드
색상 = ""
현재_속도 = 0
# 자동차의 메서드
def upSpeed(증가할_속도량):
# 현재 속도에서 증가할_속도량만큼 속도를 올리는 코드
def downSpeed(감소할_속도량):
# 현재 속도에서 감소할_속도량만큼 속도를 내리는 코드
클래스 변수 : 클래스 정의에서 메서드 밖에 존재하는 변수, 해당 클래스를 사용하는 모두에게 공용으로 사용되는 변수, 클래스명. 변수명
인스턴스 변수 : 각 객체 인스턴스마다 별도로 존재, 클래스 정의에서 메서드 안에서 사용되면서 self.변수명
처럼 사용, 각 객체별로 서로 다른 값을 갖는 변수
self.
객체변수.인스턴스변수
메서드
클래스 사용 순서
1단계
2 단계
3단계
class Car: # 1단계
color = ''
def upSpeed(self.value):
....
myCar1 = Car() # 2단계
myCar1.color = '빨강' # 3단계
myCar1.upSpeed(30) # 3단계
생성자의 개념 : 인스턴스를 생성하면서 필드값을 초기화시키는 함수
생성자의 기본
__init__()
class 클래스명:
def __init__(self):
# 이 부분에 초기화할 코드 입력
클래스 내부에 선언된 함수 : 메소드 or 멤버 함수
인스턴스들이 개별적으로 가지는 속성을 저장하는 변수 : 인스턴스 변수 or 멤버 변수 or 필드
__str__()
class Cat:
def __init__(self, name, color):
self.name = name
self.color = color
def __str__(self): # Cat 객체의 문자열 표현 방식
return 'Cat(name='+self.name+', color='+self.color+')'
nabi = Cat('나비', '검정색')
print(nabi)
# 결과
# Cat(name=나비, color=검정색)
클래스 변수 : 클래스 안에 공간이 할당된 변수, 여러 인스턴스가 클래스 변수 공간 함께 사용
class Car:
color = "" #인스턴스 변수
speed = 0 # 인스턴스 변수
count = 0 # 클래스 변수
def printMessage():
print("시험 출력")
def __init__(self):
self.speed = 0
Car.count += 1
# 변수 선언
myCar1, myCar2 = None, None
# 메인 코드 부분
myCar1 = Car()
myCar1.speed = 30
print("%dkm, %d"%(myCar1.speed, Car.count))
myCar2 = Car()
myCar2.speed = 60
print("%dkm, %d"%(myCar2.speed, myCar2.count))
# 결과
# 30km, 1
# 60km, 2
클래스의 상속(Inheritance)
: 기존 클래스에 있는 필드와 메서드를 그대로 물려받는 새로운 클래스를 만드는 것
public, protected, private등의 접근 제한자를 갖지 않는다.
Python 클래스는 기본적으로 모든 멤버가 public이라고 할 수 있다.
내부적으로만 사용하는 변수 혹은 메서드는 그 이름 앞에 하나의 밑줄(_)을 붙인다.
특정 변수명이나 메서드를 private으로 만들어야 한다면 두개의 밑줄(__)을 이름 앞에 붙이면 된다.
상속의 개념
class 자식클래스 이름(부모클래스이름):
def __init__(self, 속성값1, 속성값2):
super(자식클래스이름,self).__init__()
# 자식클래스의 초기화 코드
# ex)
class Person:
def __init__(self):
print('Person __init__')
self.hello = 'Hello.'
class Student(Person)
def __init__(self):
print('Student __init__')
super().__init__() # super으로 부모 클래스의 __init__메서드 호출
self.school = 'Python Coding'
james = Student()
print(james.school)
print(james.hello)
# 결과
# Student __init__
# Person __init__
# Python Coding
# Hello.
# 파생 클래스에서 __init__ 메서드를 생략한다면 부모 클래스의 __init__이 자동으로 호출되므로 super()는 사용하지 않아도 된다.
class Person:
def __init__(self):
print('Person __init__')
self.hello = 'Hello.'
class Student(Person)
pass
james = Student()
print(james.hello)
# 결과
# Person __init__
# Hello.
메서드 오버라이딩
상위 클래스의 메서드를 서브 클래스에서 재정의
class Car:
def upSeed(self, value):
~
class Sedan(Car):
def upSeed(self, value):
~
트럭 --> 현재 속도(슈퍼 클래스) : 200
승용차 --> 현재 속도(서브 클래스) : 150
소나타 --> 현재 속도(서브 클래스) : 150
## 클래스 선언 부분
class Car :
speed = 0
def upSpeed(self, value):
self.speed += value
print("현재 속도(슈퍼 클래스) : %d"%self.speed)
class Sedan(Car):
def upSpeed(self,value):
self.speed += value
if self.speed > 150:
self.speed = 150
print("현재 속도(서브 클래스) : %d"%self.speed)
class Sonata(Sedan):
pass
class Truck(Car):
pass
## 변수 선언 부분
sedan1, truck1 = None, None
## 메인 코드 부분
truck1 = Truck()
sedan1 = Sedan()
sonata1 = Sonata()
print("트럭 --> ", end = "")
truck1.upSpeed(200)
print("승용차 --> ",end = "")
sedan1.upSpeed(200)
print("소나타 --> ",end = "")
sonata1.upSpeed(300)
super() 함수 : 서브 클래스에서 메서드 오버라이딩을 할 때, 슈퍼 클래스의 메서드나 속성을 사용해야 하는 경우, super() 메서드를 사용하면 된다.
class Car: value = '슈퍼 값' def carMethod(self): print('슈퍼 클래스 메서드 실행 ~ ') class Sedan(Car): def carMethod(self): super().carMethod # Car 클래스의 carMethod()가 실행 print(super().value) # Car 클래스의 value가 출력된다. sedan1 = Sedan()sedan1.carMethod()
캡슐화
setXXX로 시작하는 메소드 : 세터(setter)
getXXX로 시작하는 메소드 : 게터(getter)
더블 스코어 변수명(__변수) : 선언된 클래스 안에서만 해당 이름으로 사용 가능하다.
객체의 identity operator
is 연산자 : 두 인스턴스가 같으면 True를 반환하며, 그렇지 않으면 False를 반환
is not : 반대 역할을 한다.
== : 두 인스턴스의 속성 값 즉 인스턴스 변수 값이 서로 일치하는지 확인하는데 사용
같은 문자를 할당한 경우, 같은 저장위치를 참조한다.
__del__()메서드
: 소멸자(Destructor), 생성자와 반대로 인스턴스 삭제할 때 자동 호출
__repr__()메서드
: 인스턴스를 print() 문으로 출력할 때 실행
__add__()메서드
: 인스턴스 사이에 덧셈 작업이 일어날 때 실행되는 메서드, 인스턴스 사이의 덧셈 작업 가능
비교 메서드
__it__()
: <__le__()
: <=__gt__()
: >__ge__()
: >=__eq__()
: ==__ne__()
: !=
추상 메서드(abstract method)
서브 클래스에서 메서드를 오버라이딩 : 슈퍼 클래스에서는 빈 껍질의 메서드만 만들어 놓고 내용은 pass로 채운다.
class SuperClass:
def method(self):
pass
class SubClass1(SuperClass):
def method(self):
print('SubClass -> 오버라이딩')
멀티 스레드
프로그램 하나에서 여러 개를 동시에 처리할 수 있도록 제공하는 기능
import threading
class Calculator :
number = 0
def __init__(self, number) :
self.number = number
def runCalc(self) :
hap = 0
for i in range(0, self.number+1) :
hap += i
print("1+2+3+.....+", self.number, "=", hap)
calc1 = Calculator(1000)
calc2 = Calculator(100000)
calc3 = Calculator(10000000)
th1 = threading.Thread(target = calc1.runCalc)
th2 = threading.Thread(target = calc2.runCalc)
th3 = threading.Thread(target = calc3.runCalc)
th1.start()
th2.start()
th3.start()
@staticmethod
class 클래스이름:
@staticmethod
def 메서드(매개변수1, 매개변수2)
코드
@ : 데코레이터, 메서드(함수)에 추가 기능을 구현할 때 사용한다.
클래스이름.메서드(변수1, 변수2)
@classmethod
class 클래스이름:
@classmethod
def 메서드(cls, 매개변수1, 매개변수2):
코드
class Person: count = 0 # 클래스 속성 def __init__(self): Person.count += 1# 인스턴스가 만들어질 때마다 숫자를 세야 하므로 __init__ 메서드에서 클래스 속성 count에 1을 더해준다. 클래스 속성에 접근한다는 것을 명확하게 하기 위해 Person.count와 같이 만들어준다. @classmethod def print_count(cls): print('{0}명 생성되었습니다.'.format(cls.count))# 이제 @classmethod를 붙여서 클래스 메서드를 만든다. 클래스 메서드는 첫 번째 매개변수가 cls인데 여기에는 현재 클래스가 들어온다. 따라서 cls.count처럼 cls로 클래스 속성 count에 접근할 수 있다.james = Person()maria = Person()# Person으로 인스턴스를 두 개 만들었으므로 print_count를 호출해보면 '2명 생성되었습니다.'가 출력된다. 물론 print_count는 클래스 메서드이므로 Person.print_count()처럼 클래스로 호출해준다.Person.print_count() # 2명 생성되었습니다.
@classmethod
(클래스 메서드)
abstract class
추상 클래스는 메서드의 목록만 가진 클래스
상속받는 클래스에서 메서드 구현을 강제하기 위해 사용
추상 클래스를 만들려면 import로 abc 모듈을 가져와야 한다.
추상 클래스를 상속받았다면 @abstractmethod가 붙은 추상 메서드를 모두 구현해야 한다.
from abc import *class 추상클래스이름(metaclass=ABCMeta): @abstractmethod def 메서드이름(self): 코드
from abc import *
class StudentBase(metaclass=ABCMeta):
@abstractmethod
def study(self):
pass
@abstractmethod
def go_to_school(self):
pass
class Student(StudentBase):
def study(self):
print('공부하기')
james = Student()
james.study()
# 결과
# Traceback 오류 발생
# 추상 클래스 StudentBase에서는 추상 메서드로 study와 go_to_school을 정의했다.
# 하지만, StudentBase를 상속받은 Student에서는 study 메서드만 구현하고, go_to_school 메서드는 구현하지 않았으므로 에러가 발생한다.
# 추상 클래스를 상속받았다면 @abstractmethod가 붙은 추상 메서드를 모두 구현해야 한다.
추상 메서드를 빈 메서드로 만드는 이유
추상 클래스는 인스턴스로 만들 수가 없다는 점이다. (만들 시 에러 발생)
추상 메서드를 만들 때 pass만 넣어서 빈 메서드로 만든다.
추상 클래스는 인스턴스로 만들 때는 사용하지 않으며 오로지 상속에만 사용한다.
파생 클래스에서 반드시 구현해야 할 메서드를 정해 줄 때 사용한다.
장식하는 도구이다.
@로 시작하는 것들이 데코레이터이다.
데코레이터 만들기
def trace(func):
def wrapper():
print(func.__name__, '함수 시작')
func()
print(func.name__name__, '함수 끝')
return wrapper
# 호출할 함수를 매개변수로 받음
# 호출할 함수를 감싸는 함수
# __name__으로 함수 이름 출력
# 매개변수로 받은 함수를 호출
# wrapper 함수 반환
@trace
def hello():
print('hello')
@trace
def world():
print('world')
hello()
world()
# 결과
# hello 함수 시작
# hello
# hello 함수 끝
# world 함수 시작
# world
# world 함수 끝
@데코레이터
def 함수이름():
코드
@데코레이터(인수)
def 함수이름():
코드
Decorator 추가 공부하기
참고 자료