<오늘의 학습내용>
얕은복사/깊은복사
클래스 상속
생성자
다중 상속
오버라이딩
추상 클래스
예외: 예외처리; try-except-else (+finally)
Exception 클래스
21_얕은복사(shallow copy)와 깊은복사(deep copy)
# 얕은 복사(메모리 주소만 복사)
obj1 = class_name(x, y)
obj2 = obj1
# 깊은 복사
import copy
obj3 = class_name(x, y)
obj4 = copy.copy(obj3) # 새로운 객체 4 생성
다양한 방법으로 리스트 객체를 복사하기
listA = [1, 2, 3, 4, 5]
listB = listA # 얕은복사
listC = [] # for loop을 이용한 깊은복사를 수행할 리스트
listD = [] # extend()를 이용한 깊은복사를 수행할 리스트
listE = [] # copy()를 이용한 깊은복사를 수행할 리스트
listF = [] # slicing을 이용한 깊은복사를 수행할 리스트
print(id(listA))
print(id(listB)) # listA와 같은 주소 출력
for i in listA:
listC.append(i) # for loop을 이용한 깊은복사
listD.extend(listA) # extend()를 이용한 깊은복사
listE = listA.copy() # copy()를 이용한 깊은복사
listF = listA[:] # slicing을 이용한 깊은복사
print()
print(id(listA))
print(id(listC)) # listA와 다른 주소 출력
print(id(listD)) # listA와 다른 주소 출력
print(id(listE)) # listA와 다른 주소 출력
print(id(listF)) # listA와 다른 주소 출력
(개인적으로는 .copy()가 제일 단순한 것 같다)
예제 - 깊은복사를 통해 독립적인 리스트를 생성하여 원본과 비교하기
# original score list 생성
# compute average
# create deep copy
# compute average excluding min/max scores
# compare average between two lists
original = [8.7, 9.1, 8.9, 9.0, 7.9, 9.5, 8.8, 8.3]
original.sort() # sort ascending
copy = original.copy() # deep copy
copy.pop(0) # remove first element
copy.pop() # remove last element
print(f'original: {original}')
print(f'copy: {copy}')
originalSum = round(sum(original), 2)
originalAvg = round(originalSum / len(original), 2)
print(f'original sum: {originalSum}')
print(f'original average: {originalAvg}')
copySum = round(sum(copy), 2)
copyAvg = round(copySum / len(copy), 2)
print(f'copy sum: {copySum}')
print(f'copy average: {copyAvg}')
print('original average - copy average: %.2f' % (originalAvg - copyAvg))
22_클래스 상속
# class inheritance
class NormalCar: # ParentClass/SuperClass
def __init__(self):
# attribute initiation
def drive(self):
# function 1
def back(self):
# function 2
class TurboCar(NormalCar): # NormalCar의 기능을 상속한 하위 subclass/child class
def __init__(self):
# attribute
def turbo(self):
# turbo function
myTurbo = TurboCar()
myTurbo.turbo() # 기본 기능
myTurbo.drive() # 상속된 기능
myTurbo.back() # 상속된 기능
23-24_생성자(constructor)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name} and I'm {self.age} years old.")
person1 = Person("Alice", 25)
person1.greet() # Output: Hello, my name is Alice and I'm 25 years old.
만약 subclass가 parent class를 상속할 때, parent class는 super() 함수를 통해 초기화할 수 있다.
class Parent:
def __init__(self, parent_attribute):
self.parent_attribute = parent_attribute
def parent_method(self):
print("This is a method from the parent class.")
class Person(Parent):
def __init__(self, parent_attribute, name, age):
super().__init__(parent_attribute) # Initializing the parent class
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name} and I'm {self.age} years old.")
person1 = Person("Parent Attribute Value", "Alice", 25)
person1.greet() # Output: Hello, my name is Alice and I'm 25 years old.
person1.parent_method() # Output: This is a method from the parent class.
25_다중상속
class grandSonClass(class1, class2, classN)
def __init__(self)
pass
26_Overriding: 하위 클래스에서 상위 클래스의 메서드를 재정의하는 것.
class Vehicle:
def __init__(self, brand):
self.brand = brand
def start_engine(self):
print("Engine started")
class Car(Vehicle):
def __init__(self, brand, model):
super().__init__(brand)
self.model = model
def start_engine(self): # this overrides the parent class function
super().start_engine()
print(f"{self.brand} {self.model}'s engine is now running.")
car = Car("Toyota", "Camry")
car.start_engine()
추상 클래스
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * (self.length + self.width)
# Attempting to create an instance of the abstract class will raise an error
# shape = Shape() # Raises TypeError: Can't instantiate abstract class Shape with abstract methods area, perimeter
rectangle = Rectangle(5, 3)
print(rectangle.area()) # Output: 15
print(rectangle.perimeter()) # Output: 16
28_예외
29_예외 처리
try:
x = int(input("Enter a number: "))
result = 10 / x
except ValueError:
print("Invalid input. Please enter a valid number.")
continue
except ZeroDivisionError:
print("Cannot divide by zero.")
continue
else:
print("Division successful!")
print(f"The result is: {result}")
30_finally 구문
try:
x = int(input("Enter a number: "))
result = 10 / x
except ValueError:
print("Invalid input. Please enter a valid number.")
continue
except ZeroDivisionError:
print("Cannot divide by zero.")
continue
else:
print("Division successful!")
print(f"The result is: {result}")
finally:
print("Cleanup code here...")
31_exception 클래스
try:
x = int(input("Enter a number: "))
result = 10 / x
except Exception as e:
print("An exception occurred:", type(e).__name__)
또는,
try:
x = int(input("Enter a number: "))
result = 10 / x
except Exception as e:
print("An exception occurred: {e}")
raise 키워드를 사용해 예외를 발생시킬 수 있다.
def divCalculator(n1, n2):
if n2 != 0:
print(f'{n1} / {n2} = {n1 / n2}
else:
raise Exception('cannot divide by 0')
try:
divCalculator(num1, num2)
except Exception as e:
print(f'Exception: {e}')
실습: 메시지 길이에 따라 SMS 또는 MMS 발송하기
def sendSMS(message):
if len(message) > 10:
raise Exception('Too long. It will be sent as MMS', 1)
else:
print('Send SMS')
def sendMMS(message):
if len(message) <= 10:
raise Exception('Too short. It will be sent as SMS', 2)
else:
print('Send MMS')
message = input('Enter message here: ')
try:
sendMMS(message)
except Exception as e:
print(f'e: {e.args[0]}')
print(f'e: {e.args[1]}')
if e.args[1] == 1:
sendMMS(message)
elif e.args[1] == 2:
sendSMS(message)
소감: