반응형

오류처리

다른 프로그래밍 언어와 마찬가지로 Python 코드에는 다양한 유형의 오류 및 예외가 발생할 수 있습니다.

일반적으로 Python 응용 프로그램의 오류는 컴파일 타임 오류와 런타임 오류의 두 가지 유형으로 나뉩니다.

컴파일 타임 오류는 응용 프로그램이 실행되기 전에 발생하고 런타임 오류는 응용 프로그램 실행 중에 발생합니다.

런타임 오류는 예외라고도 하며 응용 프로그램이 충돌할 가능성이 있습니다.

Python은 런타임에 데이터 유형이 평가되는 느슨한 유형의 언어이므로 Java C#과 같은 강력한 유형의 언어보다 예외가 발생할 가능성이 훨씬 더 높습니다.

 

예외처리

예외 처리는 응용 프로그램이 런타임에 충돌하지 않도록 하고 예외를 관리하는 프로세스로 정의할 수 있습니다.

예외 처리를 통해 응용 프로그램이 비정상적으로 작동하는 원인과 사용자가 응용 프로그램을 사용하여 수행하려는 작업에 대해 사용자에게 더 읽기 쉬운 메시지를 표시할 수 있습니다. 그럼 더 이상 고민하지 않고 시작하겠습니다.

 

다음 스크립트는 컴파일 타임 오류가 어떻게 보이는지 보여줍니다. 파이썬 인터프리터가 해석할 수 없기 때문에 실행되지 않습니다. 출력은 함수 매개변수가 대괄호로 지정되었기 때문에 코드에 구문 오류가 있음을 보여줍니다. 대괄호 안에 함수 매개변수를 지정해야 합니다.

 

def divide_numbers[a, b]:

  result = a / b

  print(result)

 

Output:

SyntaxError: invalid syntax

 

위의 스크립트의 오류를 수정하면 다음과 같습니다.

def divide_numbers(a, b):

  result = a / b

  print(result)

 

다음 스크립트를 실행하면 숫자를 0으로 나눌 수 없다는 오류가 발생합니다. 매개변수 b의 값으로 0을 전달할 때만 오류가 발생하는 것을 볼 수 있습니다. 이것은 예외의 예입니다.

 

def divide_numbers(a, b):

  result = a / b

  print(result)

 

divide_numbers(20, 0)

 

Output:

ZeroDivisionError: division by zero

 

예외처리 다루기

예외처리의 기본 구조는 try, exception문으로 구성되어 있습니다.

 

try:

실행 구문

except [발생 오류[as 오류 메시지 변수]]:

오류 메시지

 

try 블록 수행 중 오류가 발생하면 except 블록이 수행됩니다. 하지만 try 블록 수행 중 오류가 발생하지 않으면 except블록은 수행되지 않습니다.

 

1.     try , except만 쓰는 경우

오류 종류에 상관없이 오류가 발생하면 except블록이 수행됩니다.

 

try:

실행 구문

except :

오류 메시지

 

2.     발생 오류만 포함한 except

오류가 발생했을 때 except문에 미리 정해 놓은 오류 이름과 일치할 때만 except 블록을 수행합니다.

 

try:

실행 구문

except 발생오류:

오류 메시지

 

3.     발생 오류와 오류 메시지 변수까지 포함한 except

2번째 경우에서 오류 메시지의 내용까지 알고 싶을 때 사용하는 방법입니다.

 

try:

실행 구문

except 발생오류 as 오류 메시지 변수:

오류 메시지

 

 

Python 스크립트는 다양한 유형의 예외를 발생시킵니다. 예를 들어, 다음 스크립트는 두 가지 예외를 발생시킬 수 있습니다. 매개변수 b의 값으로 0을 전달하면 0으로 나누기 예외가 발생합니다. b에 대해 0이 아닌 값을 전달하면 다음 스크립트는 초기화되지 않은 "result_ new" 변수에 대한 값을 출력하는 예외가 발생합니다.

 

def divide_numbers(ab):

  result = a / b

  print(result_new)

 

다음 스크립트는 b0을 전달할 때 나누기 예외 발생한 경우입니다.

 

divide_numbers(20, 0)

 

Output:

NameError: name 'result_new' is not defined

 

다음 스크립트는 정상적으로 나눗셈이 이루어졌지만 result_new 변수가 초기화가 되어 있지 않아서 예외가 발생한 경우입니다.

 

divide_numbers(20, 10)

 

Output:

NameError: name 'result_new' is not defined

 

위의 예제를 보면 하나의 Python 스크립트가 여러 예외를 생성할 수 있음을 알 수 있습니다.

Python에서 예외를 처리하려면 예외를 발생할 가능성이 가장 높은 코드를 try 블록 내부에 감싸야 합니다. try 블록 다음에는 except 블록이 와야 합니다. 예외 블록에는 예외가 발생한 경우 실행하려는 코드가 포함되어 있습니다.

 

다음 스크립트는 Divide_numbers() 메서드 내에서 a b로 나누고 result_new 변수가 인쇄되는 코드가 try 블록 안에 있습니다. 예외가 발생한 경우 "예외가 발생했습니다."라는 메시지가 사용자에게 표시됩니다.

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except:

    print("an exception occurred")

 

b0을 전달하면 예외가 발생하게 되고 예외 문자가 출력됩니다.

divide_numbers(20, 0)

 

Output:

an exception occurred

 

b10을 전달하면 정상적으로 나눗셈은 이루어지지만 result_new변수가 초기화가 되지 않아서 예외가 발생하게 되고 예외 문자가 출력됩니다.

divide_numbers(20, 10)

 

Output:

an exception occurred

 

이전 스크립트에서 두 예외에 대해 동일한 메시지를 받았습니다. 다른 예외에 대해서 다른 메시지를 출력할 수 있습니다. 예외가 발생하면 Exception 클래스의 객체가 생성됩니다. 다음 스크립트와 같이 예외 블록에서 해당 객체를 사용하여 예외 메시지를 인쇄할 수 있습니다.

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except Exception as e:

    print(e)

 

divide_numbers(20, 0)

 

Output:

division by zero

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except Exception as e:

    print(e)

 

divide_numbers(20, 10)

 

Output:

name 'result_new' is not defined

 

다양한 예외를 개별적으로 처리하는 방법

다른 예외를 개별적으로 처리하고 예외 유형에 따라 except 블록에서 다른 코드를 실행할 수 있습니다.

 

다음 스크립트에는 NameError 예외와 ZeroDivisionError 예외를 잡는 두 개의 예외 블록이 있습니다. b0을 전달하면 ZeroDivisionError예외가 발생하게 됩니다.

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except NameError:

    print("변수를 사용하기 전에 초기화되지 않았습니다.")

  except ZeroDivisionError:

    print("0으로 나누는 것은 불가능합니다.")

 

divide_numbers(20, 0)

 

Output:

0으로 나누는 것은 불가능합니다.

 

정상적으로 나눗셈은 이루어졌지만 result_new변수가 초기화되지 않았기 때문에 NameError 예외가 발생하였습니다.

divide_numbers(20, 10)

 

Output:

변수를 사용하기 전에 초기화되지 않았습니다.

 

Finally 블록 사용

finally 블록은 예외 발생 여부에 관계없이 항상 실행됩니다.

finally 블록은 일반적으로 메모리 공간을 지우는 데 사용됩니다.

 

다음 스크립트에서는 Divide_numbers() 메서드 끝에 finally 블록을 추가했습니다.

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except NameError:

    print("변수를 사용하기 전에 초기화되지 않았습니다.")

  except ZeroDivisionError:

    print("0으로 나누는 것은 불가능합니다.")

  finally:

    print("항상 실행됩니다.")

 

divide_numbers(20, 10)

 

Output:

변수를 사용하기 전에 초기화되지 않았습니다.

항상 실행됩니다.

 

사용자 정의 예외처리

사용자 정의 예외를 발생시키는 가장 간단한 방법은 "raise Exception" 키워드를 사용하는 것입니다. 예외에 대한 메시지는 Exception 클래스의 생성자로 전달됩니다.

raise 키워드를 사용해서 오류를 강제로 발생시킬 수 있습니다.

 

다음 스크립트는 목록 변수 my_list 3개 이상의 항목을 삽입하려고 하면 예외가 발생합니다. my_list 4개의 항목을 추가하므로 다음 스크립트의 출력과 같이 예외가 표시됩니다.

 

my_list = []

 

for _ in range(4):

  my_list.append("Python")

  print(my_list)

if len(my_list)>3:

    raise Exception("This list cannot contain more than 3 items")

 

Output:

['Python']

['Python', 'Python']

['Python', 'Python', 'Python']

['Python', 'Python', 'Python', 'Python']

Exception: This list cannot contain more than 3 items

 

Exception 클래스를 상속받아서 사용자 정의 예외처리 클래스 만들기

Exception 클래스에서 상속되는 클래스를 생성하여 사용자 지정 이름의 예외를 정의할 수 있습니다.

 

다음 스크립트에서는 Exception 클래스에서 상속되는 ListItemOverFlow라는 사용자 지정 예외에 대한 클래스를 정의합니다. 사용자 정의 클래스 생성자에서 사용자 정의 오류 메시지를 부모클래스인 Exception 클래스 생성자에 전달합니다.

 

class ListItemOverFlow(Exception):

  def __init__(selfnew_listerror_message="Exception: This list cannot contain more than 3 items"):

    self.new_list = new_list

    self.error_message = error_message

    super().__init__(self.error_message)

 

이제 ListItemOverFlow 예외를 throw하면 ListItemOverFlow 클래스 생성자 내에서 정의한 사용자 지정 메시지와 함께 출력에 명명된 예외가 표시됩니다.

 

my_list = []

 

for _ in range(4):

  my_list.append("Python")

  print(my_list)

  if len(my_list) > 3:

    raise ListItemOverFlow(my_list)

 

Output:

['Python']

['Python', 'Python']

['Python', 'Python', 'Python']

['Python', 'Python', 'Python', 'Python']

ListItemOverFlow: Exception: This list cannot contain more than 3 items

반응형
반응형

연산자 오버로딩(Operator Overloading)

연산자 오버로딩은 객체 지향 프로그래밍의 중요한 속성입니다. 연산자에 특별한 의미를 부여하는 방법이 연산자 오버로딩입니다.

내부적으로 + 연산자는 매직 메서드로 알려진 _add_() 메서드로 구현되는 반면

* 연산자는 문자열 반복에도 적용할 수 있는 _mul_() 메서드로 구현됩니다.

 

다음 스크립트는 Boy 클래스를 만들고 b1 b2Boy 클래스 객체를 생성하였습니다. 그리고 b1, b2객체를 더하기 연산을 한 후 출력하였습니다. 그 결과 지원하지 않는다는 오류 메시지를 출력하였습니다. b1b2객체의 더하기 연산이 정의되어 있지 않기 때문에 오류가 발생하였습니다.

 

class Boy:

  def __init__(selftoys):

    self.toys = toys

 

b1 = Boy(22)

b2 = Boy(30)

print(b1 + b2)

 

TypeError: unsupported operand type(s) for +: 'Boy' and 'Boy'

 

다음 스크립트는 클래스 객체를 위한 + 연산자를 오버로딩하는 예제입니다.

class Boy:

  def __init__(selftoys):

    self.toys = toys

 

  def __add__(selfvar):

    return self.toys + var.toys

 

b1 = Boy(22)

b2 = Boy(30)

print(b1 + b2)

 

Output:

52

 

다음 표는 연산자와 관련 메서드 목록을 보여주고 있습니다.

Operator Magic methods
- object.__sub__(self, other)
+ object.__add__(self, other)
/ object.__truediv__(self, other)
* object.__mul__(self, other)
% object._mod_(self,other)
// object.__floordiv__(self, other)
+= object.__iadd__(self, other)
** object._pow_(self,other)
*= object._imul_(self,other)
-= object.__isub__(self, other)
//= object.__ifloordiv__(self,other)
**= object.__idiv__(self,other)
%= object.__ipow__(self,other)
<= object._imod_(self,other)
object.__le__(self,other)
>= object.__lt__(self,other)
object.__gt__(self,other)
!= object.__ne__(self,other)
== object.__eq__(self,other)

 

다음 스크립트는 > <= 연산자의 오버로딩의 예제입니다.

class Worker:

  def __init__(selfnamesal):

    self.name = name

    self.sal = sal

  

  def __gt__(selfvar):        # > 연산자 magic method

    return self.sal > var.sal

 

  def __le__(selfvar):        # <= 연산자 magic method

    return self.sal <= var.sal

 

w1 = Worker("A", 10000000)

w2 = Worker("B", 13000000)

print(w1 > w2)

print(w1 < w2)

print(w1 <= w2)

print(w1 >= w2)

 

Output:

False

True

True

False

 

다음 스크립트는 * 연산자를 오버로딩한 예제입니다.

class A:

  def __init__(selfsal):

    self.sal = sal

 

  def __mul__(selfvar):

    return self.sal * var.days

 

class B:

  def __init__(selfdays):

    self.days = days

 

a = A(500)

b = B(27)

print('Total Amount:', a*b)

 

Output:

Total Amount: 13500

 

메서드 오버로딩(Method Overloading)

메서드 오버로딩은 동일한 이름으로 메서드를 정의하고 매개변수를 다르게 사용하는 방법입니다. 그러나 파이썬 프로그래밍에서는 메서드 오버로딩은 사용 불가능합니다.오버로드된 메서드는 두 메서드가 동일한 이름을 공유하지만 인수가 다른 메서드입니다. 프로그래머가 동일한 이름과 다른 수의 인수를 사용하여 다양한 메서드를 선언하면 마지막 메서드가 Python 프로그래밍에서 고려됩니다(Hall 2010). 메서드 오버로딩은 파이썬에서 불가능합니다.

 

다음 스크립트는 클래스 A에 동일한 이름을 가진 method1을 매개변수만 다르게 3개 정의하였습니다. aA 클래스의 객체를 만들고 각각의 매서드를 호출하면 마지막으로 정의한 매개변수 2개를 받는 메서드만 오류가 발생하지 않습니다.

 

class A:

  def method1(self):

    print('No arg')

 

  def method1(selfx):

    print('One arg')

 

  def method1(selfxy):

    print('Two-arg')

 

a = A()

#a.method1()    # error

#a.mothod1(3)   # error

a.method1(3, 2)

 

Output:

Two-arg

 

오버로드된 메서드 처리

메서드의 매개변수 입력이 필요에 따라 개수가 변한다면 다음 스크립트처럼 처리하면 됩니다.

class Arth:

  def sum(selfx = Noney = Nonez = None):

    if x != None and y != None and z != None:

      print(x + y + z)

    elif x!= None and y != None:

      print(x + y)

    else:

      print('Default')

 

a = Arth()

a.sum(2)

a.sum(3, 4)

a.sum(2, 3, 4)

 

Output:

Default

7

9

 

다음 스크립트는 여러 개의 매개변수를 입력받기 위해서 *키워드를 사용하여 sum의 매개변수를 *x로 정의하였습니다. Arth클래스로 a객체를 생성한 후 Arth클래스 메서드인 sum을 호출하고 여러 매개변수를 입력하면 입력한 매개변수들은 튜플로 저장됩니다.

 

class Arth:

  def sum(self, *x):

    s = 0

    for i in x:

      s = s + i

    print('Sum: ', s)

    print('type:' , type(x))

 

a = Arth()

a.sum(2)

a.sum(3, 4)

a.sum(2, 3, 4)

 

Output:

Sum:  2

type: <class 'tuple'>

Sum:  7

type: <class 'tuple'>

Sum:  9

type: <class 'tuple'>

 

오버라이딩(Overriding)

오버라이딩은 자식 클래스가 부모 클래스를 상속 받는 경우 부모 클래스의 메서드 이름과 매개변수 및 반환 유형이 비슷한 자식 클래스의 메서드를 정의하면 자식 클래스에서 자체 기능을 정의할 수 있습니다. 부모클래스와 자식클래스에 동일한 이름으로 메서드가 정의되어 있으면 자식 클래스의 메서드가 호출됩니다.

부모 클래스의 메서드를 자식 클래스에서 재정의하는데 사용됩니다.

 

class Parent:

  def m1(self):

    print('Parent m1')

  def m2(self):

    print('Parent m2')

 

class Child(Parent):

  def m2(self):

    print('Child m2')

 

c = Child()

c.m2()

 

Output:

Child m2

반응형
반응형

Inner 클래스

다른 클래스 내부의 클래스 선언을 내부 클래스라고 합니다.

부모 객체가 없으면 자식 객체도 존재할 수 없습니다.

내부 클래스 객체가 존재하려면 외부 클래스 객체가 존재해야 합니다. 따라서 내부 클래스 객체는 외부 클래스 객체와 연결되어야 합니다.

다음 스크립트는 내부 클래스를 작성한 예제입니다.

 

class Scientist:

  def __init__(self):

    self.name = 'Dr. Kim'

    self.info = self.Info()   내부 객체 생성

  def method(self):

    print('Name:', self.name)

  

  class Info:                 내부 클래스 선언

    def __init__(self):

      self.height = 182

      self.weight = 70

      self.color = "Dark"

    def method(self):

      print('Height:{} Weight:{} Color:{}'.format(self.height, self.weight, self.color))

 

객체 생성

s = Scientist()   외부 객체 생성

s.method()

x = s.info        내부 객체 생성

x.method()

 

Output:

Name: Dr. Kim

Height:182 Weight:70 Color:Dark

 

상속

상속은 이미 정의된 클래스에서 새 클래스를 생성하는 방법입니다.

이미 정의된 클래스를 기본 클래스, 수퍼 클래스 또는 상위 클래스라고 하며 상속 받을 새 클래스를 하위 클래스, 파생 클래스 또는 자식 클래스라고 합니다.

 

has-a 관계

클래스에서 다른 클래스의 객체를 생성하여 다른 클래스에 있는 멤버에 액세스하는 관계입니다.

 

다음 스크립트는 has-a관계를 나타내는 예제입니다.

 

class P:

  x = 15

  def __init__(self):

    self.y = 25

  def method1(self):

    print('P class data')

 

class Q:

  def __init__(self):

    self.p = P()            # P 클래스 객체 생성

  def method2(self):

    print(self.p.x)         # p 객체로 P 클래스의 속성에 접근

    print(self.p.y)         # p 객체로 P 클래스의 인스턴스 멤버에 접근

    self.p.method1()        # p 객체로 P 클래스의 인스턴스 메서드에 접근

 

q = Q()

q.method2()

 

Output:

15

25

P class data

 

is-a 관계

상속의 주요 이점은 코드 재사용성 또는 기존 기능을 새로운 기능으로 확장하는 것입니다. 상위 클래스의 기능을 확장하려는 경우 상위 클래스의 메서드, 변수 및 생성자를 하위 클래스에 다시 작성할 필요가 없습니다.

다음 스크립트는 is-a관계를 나타내는 예제입니다.

 

class Side:

  def method1(self):

    print("Parent method-1")

 

class Guide(Side):     # Side 클래스 상속 받음

  def method2(self):

    print("Child method-2")

 

g = Guide()

g.method1()

g.method2()

 

Output:

Parent method-1

Child method-2

 

is-a vs has-a 관계

IS-A 관계를 사용하면 새 기능을 추가하여 기능을 확장할 수 있지만 HAS-A 관계에서는 새 기능으로 기능을 확장할 수 없습니다. 기존 기능만 사용할 수 있습니다.

 

다음 그림은 직원 클래스는 person 클래스의 기능을 확장하는 반면 직원 클래스는 확장하지 않고 회사의 기능만 사용하고 있습니다.

is-a vs has-a 관계

 

상속의 유형

1.    단일 상속(Single Inheritance)

단일 상속은 한 클래스의 속성을 다른 클래스로 상속할 수 있습니다. 다음 그림은 클래스 S의 속성은 클래스 P에 상속될 수 있습니다.

 


 
def method1(self):class
 Parent:

    print("Parent Method")

 

class Child(Parent):

  def method2(self):

    print("Child Method")

 

c = Child()

c.method1()

c.method2()

 

Output:

Parent Method

Child Method

 

2.    다중 수준 상속(Multilevel Inheritance)

하나 이상의 부모 클래스를 포함하지만 다른 수준에 있는 상속을 다중 수준 상속이라고 합니다. 다음 그림은 클래스 V의 속성은 클래스 S에 상속되고 클래스 S의 속성은 클래스 P에 상속될 수 있습니다.

 

class Parent:

  def method1(self):

    print("Parent Method")

 

class Child(Parent):

  def method2(self):

    print("Child Method")

 

class SubChild(Child):

  def method3(self):

    print("Sub Child Method")

 

c = SubChild()

c.method1()

c.method2()

c.method3()

 

Output:

Parent Method

Child Method

Sub Child Method

 

3.    계층적 상속(Hierarchical Inheritance)

계층적 상속은 한 클래스의 속성은 같은 수준의 여러 클래스에 상속될 수 있습니다. 다음 그림은 클래스 P의 속성은 클래스 S와 클래스 V에 상속될 수 있습니다.

 

class Parent:

  def method1(self):

    print("Parent Method")

 

class Child1(Parent):

  def method2(self):

    print("Child-1 Method")

 

class Child2(Parent):

  def method3(self):

    print("Child-2 Method")

 

c1 = Child1()

c1.method1()

c1.method2()

c2 = Child2()

c2.method1()

c2.method3()

 

Output:

Parent Method

Child-1 Method

Parent Method

Child-2 Method

 

4.    다중 상속(Multiple Inheritance)

다중 상속은 하나 이상의 부모 클래스로부터 상속이 가능합니다. 이 경우 부모 클래스의 모든 메서드와 속성은 상속 후 자식 클래스에 표시됩니다. 다음 그림은 클래스 S와 클래스 V의 속성은 클래스 P에 상속됩니다.

 

class A:

  def method1(self):

    print("A class")

 

class B:

  def method2(self):

    print("B class")

 

class C(A, B):

  def method3(self):

    print("C class")

 

c = C()

c.method1()

c.method2()

c.method3()

 

Output:

A class

B class

C class

 

5.    하이브리드 상속(Hybrid Inheritance)

단일 상속, 다중 수준 상속, 다중 상속 및 계층적 상속을 결합한 것을 하이브리드 상속이라고 합니다. 다음 그림6은 하이브리드 상속의 예입니다.

 

6.    순환 상속(Cyclic Inheritance)

순환 상속은 한 클래스의 속성을 다른 클래스에 순환적으로 상속할 수 있습니다.

 



반응형
반응형

다형성(Polymorphism)

다형성을 사용하면 동일한 기능을 다르게 작동시킬 수 있습니다.

예를 들어, 다음 스크립트에 있는 메소드는 두 개의 필수 매개변수 값 a b와 하나의 선택적 매개변수 c를 사용하였으며 기본값을 0으로 설정하였습니다.

 

세 개의 매개변수에 대한 값을 전달하면 세 개의 매개변수 값의 합계가 반환됩니다. 두 개의 값을 전달하면 c c 값이 할당됩니다. 매개변수 c의 값이 0이면 b에서 b를 빼고 값을 반환합니다.

 

def my_func(abc=0):

  if c == 0:

    return a - b

  else:

    return a + b + c

 

my_func()메서드의 2개 또는 3개의 매개변수를 입력한 후 출력한 결과입니다. 출력은 세 개의 매개변수를 my_func() 함수에 전달할 때 3 매개변수의 합이 반환됨을 보여줍니다. 그렇지 않고 두 개의 매개변수를 전달하면 첫 번째 매개변수에서 두 번째 매개변수 값을 빼서 결과를 반환합니다.

 

print(my_func(10, 20, 30))

print(my_func(10, 20))

 

Output:

60

-10

 

상속을 통해 다형성을 구현하려면 부모 클래스에서 구현된 메서드를 재정의해야 합니다. 메서드를 재정의한다는 것은 부모 클래스와 자식 클래스에 같은 이름을 가진 메서드를 갖는 것을 의미합니다. 이 경우 자식 클래스가 부모 클래스 메서드를 재정의합니다. 자식 클래스 객체를 사용하여 해당 메서드를 호출하면 메서드의 자식 클래스 구현이 실행됩니다.

 

다음 스크립트는 display_shape_attr() 메서드를 사용하여 Shape라는 클래스를 정의합니다.

 

class Shape:

  def __init__(selfnamearea):

    self.shape_name = name

    self.area = area

  

  def display_shape_attr(self):

    print("The shape name is ", self.shape_name)

    print("The shape area is ", self.area)

 

자식 클래스 Circle은 부모 Shape 클래스를 상속합니다. 자식 클래스에서도 display_shape_attr() 메서드를 재정의하고 자체 구현을 합니다.

class Circle(Shape):

  def __init__(selfnamearearadius):

    super().__init__(name, area)

    self.radius = radius

  

  def display_shape_attr(self):

    print("The shape name is ", self.shape_name)

    print("The shape area is ", self.area)

    print("The radius of the circle is ", self.radius)

 

마찬가지로 Square 클래스도 Circle클래스처럼 Shape 클래스를 상속하고 display_shape_attr() 메서드를 재정의하고 자체 구현을 합니다.

 

class Square(Shape):

  def __init__(selfnameareavertices):

    super().__init__(name, area)

    self.vertices = vertices

  

  def display_shape_attr(self):

    print("The shape name is ", self.shape_name)

    print("The shape area is ", self.area)

    print("Total number of vertices in a square ", self.vertices)

 

이제 Shape, Circle Square 클래스의 객체를 만들고 display_shape_attr() 메서드를 호출하면 해당 객체가 display_shape_attr() 메서드를 실행하는 것을 볼 수 있습니다. , 클래스에 따라 같은 이름의 메서드를 사용하여 다른 논리를 구현하는 다형성을 사용한 것입니다.

 

shape = Shape("Shape", 500)

circle = Circle("Circle", 700, 400)

square = Square("Square", 500, 4)

 

shape.display_shape_attr()

print("------------------------------------")

circle.display_shape_attr()

print("------------------------------------")

square.display_shape_attr()

 

 

Output:

The shape name is  Shape

The shape area is  500

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

The shape name is  Circle

The shape area is  700

The radius of the circle is  400

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

The shape name is  Square

The shape area is  500

Total number of vertices in a square  4

 

반응형

+ Recent posts