[Python]객체지향프로그래밍

2023. 12. 22. 16:29· 공부/Python
목차
  1. 예제
  2. 예제2
  3. 클래스 변수
  4. 상수
  5. 특수 메소드(연산자 함수)
  6. 예제. 분수 클래스 작성
  7. 상속
  8. 상속 필요성
  9. 부모 클래스의 생성자 호출
  10. 다중 상속 : 부모 생성자 호출
  11. has - a 관계 : 포함
  12. 클래스메소드와 정적메소드 차이
  13. 메소드 오버라이딩
  14. 다형성
  15. Object 클래스
  16. repr() 메소드 재정의
  17. call() 메소드
  18. callable() 함수
반응형

 

예제

  • TV 객체 추상화
    • 상태(속성) → 상태를 동작 보다 먼저 정의
      • 전원상태, 볼륨, 채널번호
    • 동작(기능)
      • 전원 켜기/끄기, 볼륨 변경하기, 채널 변경하기
  • TV 클래스 모델링
    • 필드(인스턴스 변수) → 상태(속성) 표현
      • on, volume, channel
    • 메소드(멤버함수) → 동작(기능) 표현
      • turnOn() , turnOff() , changeVolume(), changeChannel()
class Tv:
  def __init__(self, on, ch, vol): # 생성자 - 필드 초기화
    self.on = on                   # 필드 = 인스턴스 변수 생성
    self.channel = ch
    self.volume = vol

  def print(self):                 # 메소드 = 멤버 함수
    print(self.on, self.channel, self.volume)

  def turnOn(self):
    self.on = True

  def turnOff(self):
    self.on = False

  def changeChannel(self, ch):
    self.channel = ch
    
  def changeVolume(self, vol):
    self.volume = vol

t1 = Tv(False, 11, 10)    # Tv 객체 생성
t1.turnOn()               # 메소드 호출
t1.print()

res : True 11 10

파이썬의 필드는 init (생성자)안에 선언

예제2

  • 자동차 객체 추상황
    • 상태(속성) → 모델, 색상, 속도
    • 동작(기능) → 가속, 감속
  • 클래스 모델링 : Car
    • 필드(인스턴스 변수) → model, color, speed
    • 메소드(멤버함수) → init() , speedUp(), speedDown(), str()
      • str() 메소드 → 객체의 상태를 문자열로 변환(반환)
      • 객체를 화면 출력 시 , 문자열로 변환 시 자동 호출
class Car:
  def __init__(self, m, c, s):   # 생성자
    self.model = m
    self.color = c
    self.speed = s

  def speedUp(self):
    self.speed += 10

  def speedDown(self):
    self.speed -= 10

  def __str__(self):
    return "Car[Model=%s:color=%s:speed=%d]" \
      % (self.model, self.color, self.speed)

c = Car('BMW', 'Black', 100)
c.speedDown()
print(c)

res : Car[Model=BMW:color=Black:speed=90]

클래스 변수

  • 클래스 변수는 클래스 당 하나만 생성된다 or 클래스 간 공유를 한다.
class Tv:
  serialnum = 0                    # 클래스 변수 정의(초기화)
  def __init__(self, on, ch, vol): # 생성자 - 초기화
    self.on = on                   # 필드 = 인스턴스 변수 생성
    self.channel = ch
    self.volume = vol
    Tv.serialnum += 1              # 객체 생성 시 클래스 변수 증가
    self.num = Tv.serialnum

  def print(self):                 # 메소드 = 멤버 함수
    print(self.on, self.channel, self.volume, self.num)


t1 = Tv(False, 11, 10)    # Tv 객체 생성
t1.print()

t2 = Tv(True, 9, 20)
t2.print()

상수

  • 상수 : 한 번 정의 되면 값이 바뀌지 않는 수
  • 값이 바뀌지 않기 때문에 메모리 절약을 위해 클래스당 하나 만 있으면 되기때문에 클래스 변수에 정의
  • 상수도 클래스의 필드에 정의하지 않고 클래스 변수에 정의한다.
class Circle:
  PI = 3.14              # 클래스 변수 정의(초기화) - 상수 정의
  def __init__(self, r):
    self.radius = r
  def area(self):
    return Circle.PI*self.radius**2
  def perimeter(self):
    return 2*Circle.PI*self.radius
  
radius = float(input('반지름의 길이 입력 :'))
c1 = Circle(radius)
print("원의 넓이 = ", c1.area())
print("원의 둘레길이 = ", c1.perimeter())

특수 메소드(연산자 함수)

class Vector2D:         # 2차원 벡터
  def __init__(self, x, y):
    self.x = x
    self.y = y

  def __eq__(self, o):         # 연산자 == 함수
    return self.x == o.x and self.y == o.y         # 1번째 클래스의 x 값과 2번째 클래스의 x값이 같은가
  
  def __add__(self, o):       # 연산자 + 함수
    return Vector2D(self.x + o.x, self.y + o.y)

  def __str__(self):
    return '(%d, %d)' % (self.x, self.y)


v1 = Vector2D(2, 3)
v2 = Vector2D(1, 2)
print(v1 == v2)         # 연산자에서 객체가 오면 객체의 연산자 함수를 사용한다
v3 = v1 + v2
print(v3)

res : False (3, 5)

예제. 분수 클래스 작성

class Fraction:
  def __init__(self, ja, mo):
    self.ja = ja
    self.mo = mo

  def __add__(self, fr):  # 더하기 연산자 수행
    return Fraction(self.ja + fr.ja, self.mo + fr.mo)   # class 사용으로 문자열 출력 사용

  def __mul__(self, fr): # 곱셈 연산자 수행
    return Fraction(self.ja * fr.ja, self.mo * fr.mo)

  def __str__(self):    # 문자열 출력
    return "%d/%d" %(self.ja, self.mo)

f1 = Fraction(2,3)
f2 = Fraction(1,2)

print(f1+f2)
print(f1*f2)

답 :
3/5
2/6

상속

  • 기존 클래스로부터 멤버(필드, 메소드)를 물려 받는다.
    • 기존 클래스 → 부모 클래스
    • 상속 받은 클래스 → 자식 클래스
  • 파이썬에서는 부모 클래스로부터 메소드를 물려 받음
    • 필드는 부모 클래스 메소드가 호출될 때 물려 받는다.
      • 메소드 사용전에는 필드가 메모리상에 없어 공간절약 가능
  • 클래스 간의 “is - a “ 관계 성립 시 활용
    • A is-a B → B 부모 클래스, A 자식 클래스
    • 학생은 사람이다.
    • 자동차는 차량이다.

상속 필요성

  • 코드의 재 사용
  • 중복 줄이기
  • 상속으로 중복 감소의 예
    • 3가지 종류의 자동차 클래스 작성
      • ex)Car, Truck, Bus
      • 공통 메소드 포함 → 클래스에서 공통 메소드 각각 작성 : 코드 중복
        • ex) setSpeed(), turn()
  • 공통 메소드를 가지는 부모 클래스 작성
    • ex) Vehicle
    • 다른 클래스는 자식 클래스로 작성
      • 공통 메소드를 물려 받음
      • 공통 메소드는 한번만 작성 → 중복 감소

부모 클래스의 생성자 호출

  • 파이썬 부모 클래스 생성자 호출 방법
    • super().init() → self 생략
    • 부모 클래스 생성자 호출로 부모 클래스의 필드를 물려 받음

다중 상속 : 부모 생성자 호출

super 에서는 self 를 안쓰는 이유는 super() 자체가 객체 이기 때문에 self를 안써도됨

# 다중 상속 : 부모 생성자 호출
class Car :
  def __init__(self):
    print('Car')

class Plane :
  def __init__(self):
    print('Plane')

class FlyingCar(Car, Plane):  # 다중 상속
  def __init__(self):
    super().__init__()        # Car 출력 -> 첫번째 부모 클래스
    Car.__init__(self)        # Car 출력
    Plane.__init__(self)      # Plane 출력

fc = FlyingCar()

Car Car Plane

has - a 관계 : 포함

  • 객체 A,B 간에 A “has-a” B 성립
    • ex)원기둥 has-a 원(밑면)

포함은 → 필드로 자연스럽게 포함

# has-a 관계 : 포함
class Circle:
  def __init__(self, r):
    self.radius = r
  def __str__(self):
    return "Circle[radius=%d]" % (self.radius)

class Cylinder:
  def __init__(self, c, h):
    self.underside = c     # 필드1: 밑면(원) => 원기둥 has-a 원(밑면)
    self.height = h        # 필드2: 높이
  def __str__(self):
    return "Cylinder[underside=%s, height=%d]" %(self.underside, self.height)

c = Circle(10)   # 반지름 10인 원 생성
cyl = Cylinder(c, 20)  # 밑면 반지름 10인 원, 높이 20인 원기둥 생성

print(cyl)

→ 원기둥은 밑면에 원을 포함한다 그러므로 상속관계가 아니라 포함관계이다. 원기둥의 필드에 원이 포함되었다.

클래스메소드와 정적메소드 차이

  • 정적메소드는 전달받는 값이 없다, 클래스메소드는 클래스명으로 전달받을 수 있다.

중요!!

class Parent:
  def __str__(self):
    return "Parent"

  @classmethod
  def method1(cls) : # 클래스 메소드 호출 시 클래스명을 cls로 전달 받는다.
    return cls()

  @staticmethod
  def method2() :   # 클래스 메소드 호출 시 클래스명을 전달받을 수 없음
    return Parent()

class Child(Parent):
  def __str__(self):
    return "Child"

obj1 = Child.method1()  # 자식 클래스이름으로 클래스 메소드 호출
print(obj1)
obj2 = Child.method2()  # 자식 클래스 이름으로 정적 메소드 호출
print(obj2)

Child Parent

메소드 오버라이딩

  • 자식 클래스에서 부모 클래스로부터 상속받은 메소드를 재정의(overriding)
class Shape:
  def draw(self):
    print('Shape Draw')

class Circle(Shape):
  def draw(self):                 # 메소드 재정의(Overriding)
    print('Circle Draw')

c = Circle()
c.draw()

다형성

  • 많은(poly) + 모양(morph)
  • 하나의 식별자로 다양한 타입(클래스)을 처리
  • 다형성 성립 조건
    • 클래스 작성
      • 상속 관계
      • 메소드 재정의(오버라이딩)
    • 객체 생성
      • 업캐스팅 → 리스트에 자식 객체 저장
      • 재정의된 메소드 호출 → 다형성 발생
# 상속과 다형성 예: 도형
class Shape:
  def __init__(self, name):
    self.name = name

  def getArea(self): # 추상메소드 => 구현 생략
    pass      

class Circle(Shape):
  def __init__(self,name, radius):
    super().__init__(name)
    self.radius = radius

  def getArea(self):    # 메소드 오버라이딩
    return 3.14 * self.radius ** 2

class Rectangle(Shape):
  def __init__(self, name, width, height):
    super().__init__(name)
    self.width = width
    self.height = height

  def getArea(self):   # 메소드 오버라이딩
    return self.width * self.height

shapeList = [ Circle("c1", 10) , Rectangle("r1", 10, 10) ]   # 업캐스팅(객체 리스트)
for s in shapeList :
  print(s.getArea())  # 재정의된 메소드 호출 ==> 다형성 발생 !!!!!!!!

314.0 100

Object 클래스

  • 파이썬 클래스 계층구조의 최상위 클래스
  • 모든 클래스의 부모 클래스
  • object 클래스 메소드 → 파이썬 모든 클래스가 상속받음
    • 각 클래스에서 재정의(overriding) 해서 사용

Untitled.png

repr() 메소드 재정의

  • 객체를 표현하는 문자열을 반환하는 특수 메소드
  • str() 메소드와 차이

Untitled.png

  • 주로 개발자가 사용하는 것
  • str() 메소드 미구현 시
    • repr() 메소드가 호출된다.
class Book :
  def __init__(self, title, isbn):
    self.__title = title
    self.__isbn = isbn

  def __repr__(self):
    return "Book('%s', '%s')" %(self.__title, self.__isbn)
  
  def __str__(self):
    return "ISBN1 : " + self.__isbn+ "; TITLE : " + self.__title

book = Book("The Python Tutorial", "0123456")
print(book)
print(repr(book))

ISBN1 : 0123456; TITLE : The Python Tutorial Book('The Python Tutorial', '0123456')

call() 메소드

  • 호출 가능한 객체를 만드는 메소드
    • 객체 참조변수를 함수처럼 사용 시 호출됨
  • 메소드 형식
    • def call(self, …) :
class Foo :
  def __init__(self, x=0) : # 생성자
    self.x = x
  
  def __str__(self):        # 객체 => 문자열 메소드
    return '[Foo : x=%d]' % self.x

  def __call__(self, *args): # 호출 가능 객체, 가변 인자
    print('__call__ method', args)

f1 = Foo(5)   # __init__ 메소드 호출
print(f1)     # __str__ 메소드 호출
f1()          # __call__ 메소드 호출
f1(1,2,3)     # __call__ 메소드 호출

[Foo : x=5] __call__ method () __call__ method (1, 2, 3)

callable() 함수

  • callable(obj) 함수
    • 참조변수 obj가 호출 가능한 객체인지를 체크
      • 호출 가능하면 True, 아니면 False 반환
class A:
  def __call__(self):
    return 'test...'

class B:
  pass

a = A()
b = B()

print(callable(a))  # True
print(callable(b))  # False

True False

반응형
  1. 예제
  2. 예제2
  3. 클래스 변수
  4. 상수
  5. 특수 메소드(연산자 함수)
  6. 예제. 분수 클래스 작성
  7. 상속
  8. 상속 필요성
  9. 부모 클래스의 생성자 호출
  10. 다중 상속 : 부모 생성자 호출
  11. has - a 관계 : 포함
  12. 클래스메소드와 정적메소드 차이
  13. 메소드 오버라이딩
  14. 다형성
  15. Object 클래스
  16. repr() 메소드 재정의
  17. call() 메소드
  18. callable() 함수
'공부/Python' 카테고리의 다른 글
  • [Python]텍스트 처리
  • [Python]넘파이 배열
  • [Python]맷플롯립
  • [Python]판다스
Future0_
Future0_
rm -rf /
Future0_
Luna Developer Blog
Future0_
전체
오늘
어제
  • 분류 전체보기 (112)
    • 프로그래밍 (4)
      • 알고리즘 (4)
    • 보안 (14)
      • Dreamhack (4)
      • Hackthebox (1)
      • Webhacking (9)
    • 프로젝트 (4)
    • 공부 (80)
      • Database (2)
      • Python (11)
      • System (4)
      • Java (13)
      • JSP (13)
      • Spring (11)
      • Kotlin (16)
      • 자료구조 (10)
      • 기계학습 (0)
    • Docker (4)
    • Github (2)
    • Tip (1)
    • 잡담 (2)

블로그 메뉴

  • 홈
  • 태그

공지사항

인기 글

태그

  • Android Studio
  • 디버깅키해시
  • SpringBoot
  • Java
  • Database
  • 자바빈즈
  • 1.9.22
  • ViewModel
  • 자료구조
  • Kotlin
  • 컴퓨터
  • 코틀린기본문법
  • api 통신
  • native app
  • shared preference
  • 프로그래밍
  • Python
  • docker
  • android studio 삭제
  • jsp
  • webhacking
  • cs
  • 키 해시
  • 상속
  • React
  • dreamhack
  • 보안
  • 알고리즘
  • Computer science
  • spring

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.0
Future0_
[Python]객체지향프로그래밍
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.