Python[2주차-2일] 클래스, 예외,텍스트(중급5~9)

이동일·2023년 7월 12일

Python

목록 보기
6/10

시작하기에 앞서.... 최대한 정리를 짧게 해보려고 했으나...
하루 수업량이 많아 정리할 내용도 많다!! 내용이 어렵다
벌써 머리 아프면 안 되는데... 적어도 EDA 가서는 머리가 아파야지... 이런

1-1 객체와 메모리, 얕은복사 깊은복사

  • 변수는 객체의 메모리 주소를 저장하고 이를 이용하여 객체를 차참조한다.
  • 얕은 복사: 객체 주소를 복사하는 것으로 객체 자체가 복사되지 않는다.(2개의 변수 메모리 주소가 같다)
  • 깊은 복사: 객체 자체를 복사하는 것으로 또 하나의 객체가 만들어진다.(2개의 변수 2개의 메모주소)

(얕은복사(상단), 깊은 복사(하단))

실습

class TemCls:


    def __init__(self, n, s):
        self.number = n
        self.str = s


    def printClsInfo(self):
        print(f'self.number: {self.number}')
        print(f'self.str: {self.str}')

#얕은복사 실습
 tc1 = TemCls(10, 'Hello')
 tc2 = tc1

 tc1.printClsInfo()
 tc2.printClsInfo()#tc1,tc2 동일결과

 print('---변경된값 확인----------------------')
 tc2.number = 3.14
 tc2.str = 'bye'

 tc1.printClsInfo()
 tc2.printClsInfo()


#깊은 복사
# import copy
# tc1= TemCls(10, 'Hello')
# tc2 = copy.copy(tc1)
#
# print('-----같은값이 출력된다-------')
# tc1.printClsInfo()
# tc2.printClsInfo()
#
# print('------------tc2만 변경된다.-----')
# tc2.number = 3.14
# tc2.str = 'Bye'
#
# tc1.printClsInfo()
# tc2.printClsInfo()
  1. 얕은복사 정리
  • tc1과 tc2가 같으므로 실습에서
    tc2 하나만 변경을 해도 둘 다 변경이 된다.
    이것이 얕은 복사이다.
  1. 깊은 복사 정리
  • imprt copy를 이용하여 tc1을 copy를 할경우
    첫 출력은 같게 출력이 되지만 tc2 데이터를 변경하면
    tc2만 변경이 된다.

1-2클래스 상속과 생성자

  • 클래스는 또 다른 클래스를 상속해서 내 것처럼 사용할 수 있다.
  • 실습 예제로 확인해보자
class NormalCar:

    def drive(self):
        print('[NormalCar] drive() called!!')

    def back(self):
        print('[NormalCar] back() called!!')


class TurboCar(NormalCar):  #괄호()를 사용하여 상속할 클래스명을 적어주자

    def turbo(self):
        print('[TurboCar] turbo() called')


myTurboCar = TurboCar()
myTurboCar.turbo()
myTurboCar.drive()# NormalCar클래스에서 상속
myTurboCar.back()# NormalCar클래스에서 상속
  • 하위 클래스 TurboCar의 괄호안에 상위 class 이름이 적혀 있다.
    하위 클래스 괄호안에 상위 class 명을 넣으므로 상속을 한다.
  • 출력 부분을 확인하면 drive()와 back()은 원래 하위 클래스의
    함수가 아니지만, 상속을 해서 사용이 가능해졌다.

생성자

  • 객체가 생성될 때 생성자를 호출하면 init()가 자동 호출된다.
  • 클래스의 생성자(constructor)이며 객체가 생성될때 자동으로 호출된다.
  • init을 정의하면 객체가 생성될 때 초기화 작업을 할수 있다.
    -self 매개변수를 통해 해당 객체에 접근한다.
  • 객체가 생성될 때마다 호출되므로 각 객체의 속성은 서로 다른 값을 가진다
  • 상위 클래스의 속성을 초기화 하기 위해서 super()를 이용한다.
class Calculator:

    def __init__(self):
        print('[Calculator] __init__() called!!')


cal = Calculator()#__init__ 자동 호출한다.


class Calculator:

    def __init__(self,n1, n2):
        print('[Calculator] __init__() called!!')
        self.num1 = n1
        self.num2 = n2

cal = Calculator(10, 20)#__init__ 자동 호출한다.
print(f'cal.num1:{cal.num1}')
print(f'cal.num2:{cal.num2}')



#다음과 같이 출력된다.
#[Calculator] __init__() called!!
#[Calculator] __init__() called!!
#cal.num1:10
#cal.num2:20





               
        
        
 #하나만 넣기
 
 class Calculator:

    def __init__(self, n):
        print('[Calculator] __init__() called!!')
        self.num1 = n
        self.num2 = 100

cal = Calculator(3.14)#__init__ 자동 호출한다.
print(f'cal.num1:{cal.num1}')
print(f'cal.num2:{cal.num2}')


1-3 다중상속, 오버라이딩, 추상클래스

  • 말 그래도 "다중" 한개 클래스가 아닌 두 개 이상의 클래스로부터 상속을 담을 수 있다.
  • 여러 개의 상위 클래스부터 속성과 메서드를 상속받아서 하위 클래스는 상위 클래스의 특징을 갖게 된다.
  • 구문형태 class penguinClass(a,b)
  • 코드의 재사용성을 높일 수 있다.
  • 클래스간 관계가 복잡해진다.
class Car01:
    def drive(self):
        print('drive() method called!!')

class Car02:
    def turbo(self):
        print('turbo() method called!!')


class Car03:
    def fly(self):
        print('fly() method called!!')



class Car(Car01, Car02, Car03):#배열로 3개를 상속한다.
    def __init__(self):
        pass

myCar = Car()

myCar.drive()
myCar.turbo()
myCar.fly()
  • 클래스 Car는 상위 클래스 Car01,Car02,Car03을 상속받아 상위 클래스의 기능을 사용하였다.

오버라이딩

  • 하위 클래스에서 클래스의 메서드를 재정의(override)한다.
  • 하위 클래스에서 상위 클래스의 같은 이름을 가진 메서드를 재정의하여 하위 클래스의 동작을 변경한다.
#오버라이딩 예시
class Robot:


    def __init__(self, c, h, w):
        self.color = c
        self.height = h
        self.weight = w


    def fire(self):
        print('미사일 발사!')

    def printRobotInfo(self):
        print(f'self.color : {self.color}')
        print(f'self.height : {self.height}')
        print(f'self.weight : {self.weight}')





class NewRobot(Robot):
    def __init__(self, c,h,w):
        super().__init__(c,h,w)


    def fire(self):
        print('레이저 발사!')# 상위 fire를 미사일발사에서 레이저 발사로 변경
                           # 이것이 오버라이딩이다.
myRobot = NewRobot('red', 200, 300)
myRobot.printRobotInfo()
myRobot.fire()
  • 상위 클래스 Robot의 함수
    def fire 를 하위 클래스에서 상속하여
    미사일 발사를 레이저 발사로 변경했다.
    (이것이 오버라이딩 이다.)

추상 클래스

  • 상위 클래스에서 하위 클래스에 메서드 구현을 강요

  • 추상 메소드는 하위 클래스에서 반드시 구현되어야 한다.

  • 추상 메소드를 정의할때는 @abstractmeThod 데코레이더를 사용한다..

  • from abc import ABCMeta

  • from abc import abstractmethod

  • class""(metaclass=ABCMeta)
    @abstractmethod


#상위클래스
  @abstractmethod #강제 구현
    def flight(self):
        pass
        
        
#하위클래스     
     def flight(self):
        print('시속 400km')      
        
        
        
        

1-3 예외,처리, try~except~else

  • 문법에는 문제가 없으나 실행 중 예상치 못한 문제

  • 예를들어 0으로 나누었을때 예외 오류 발생!

  • 예외 관련 클래스는 Exception 클래스를 상속한다.

예외처리

  • 예상치 못한 예외 프로그램 전체에 영향이 없도록 처리한다.
  • 예외 발생 예상 구문을 try~except로 감싼다.
n1 = 10; n2 = 0

try:
    print(n1/n2)

except:
    print('예상치 못한 문제가 발생했습니다.')
    print('다음 프로그램이 정상 실행됩니다.')


print(n1 * n2)
print(n1 - n2)
print(n1 + n2)

예외처리 try~except~else

  • 예외가 발생하지 않은 경우 실행하는 구문이다.
  • 예외가 발생할 수 있는 코드 블록 실행하고, 예외 발생시 처리하고자 하는 예외를 except 에서 처리한다.
  • 예외 미발생시 try 블록 이후의 코드를 실행하는 else 블록을 사용할 수 있다.
nums = []

n = 1
while n <6:
    try:

        num = int(input('input number: '))
    except:
        print('예외 발생!')
        continue

    else:
        if num % 2 ==0:
            nums.append(num)
            n +=1

        else:
            print('홀수 입니다.', end ='')
            print('다시 입력')
            continue

print(f'nums: {nums}')

finally!

  • 예외 발생과 상관없이 항상 실행

try:
    inputData = input('input number:')
    numInt = int(inputData)

except:
    print('exception raise!')
    print('not number!!')

else:
    if numInt % 2 ==0:
        print('even number!!')

    else:
        print('odd number')

finally: #예외든 아니든 실행 된다.
    print(f'inputData: {inputData}')

Exception 클래스 ,raise

  • 이전까진 에러를 예외를 해서 에러를 볼수 없었는데 Exception을 사용해서 원인을 파악해보자
  • 밑에 실습을 확인하여 에러 메시지를 확인 해보자
num1 = int(input('input number1:'))
num2 = int(input('input number2:'))



try:
    print(f'num1 / num2 = {num1 / num2}')
except Exception as e: #에러 확인
    print('0으로 나눌 수 없습니다.')
    print(f'exception: {e}')

print('-----------------')
print(f'num1 * num2 = {num1 * num2}')
print(f'num1 - num2 = {num1 - num2}')
print(f'num1 + num2 = {num1 + num2}')




#결과출력 해보면 division by zero 오류를 확인할수 있다.

#input number1:10
#input number2:0
#0으로 나눌 수 없습니다.
#exception: division by zero

#num1 * num2 = 0
#num1 - num2 = 10
#num1 + num2 = 10
#Process finished with exit code 0

사용자 예외 클래스

  • Exception 클래스를 상속해서 사용자 예외 클래스를 만들 수 있다.
class NotUseZeroException(Exception):


    def __init__(self, n):
        super().__init__(f'{n}은 사용할 수 없습니다.')



def divCalculator(n1, n2):

    if n2 ==0:
        raise NotUseZeroException(n2)

    else:
        print(f'{n1} / {n2} = {n1/ n2}')


num1 = int(input('input number1: '))
num2 = int(input('input number2: '))


try:
    divCalculator(num1, num2)
except NotUseZeroException as e:
    print(e)

1-4 텍스트 with~as,writelines(), readlines(),readline()

with~as

  • 파일 닫기(close)를 생략할 수 있다.
  • 파일을 열고 닫는 등 작업을 별도로 처리하지 않아도 되고 코드가 간결해지고 가독성이 좋다.
  • close()를 안해도 된다.

with open(uri + '5_037.txt', 'a') as f: #f라 부르겠다.
    f.write('python study!!')

with open(uri + '5_037.txt', 'r') as f: #f라 부르겠다.
    print(f.read())
#with as로 인해 close()사용 안해도 된다.

writelines()

  • List 또는 tuple 데이터를 파일에 쓰기 위한 함수이다.
  • 여러 줄의 텍스트를 한 번에 사용할때 좋다
languages= ['c/c++', 'java', 'c#', 'python','javascript']


uri = 'C:/pythonTxt/'
for item in languages: #writelines() 함수 사용할때는 반복문 필요없다. 내부적으로 반복가능하게 처리한다.
with open(uri + 'languages.txt', 'a') as f:
        # f.write(item)
        # f.write('\n')
        f.writelines(item +'\n'  for item in languages)# item +'n'  item을 개행해서 사용

# with open(uri + 'languages.txt', 'r') as f: #r로 읽어 들여보기
#
#    print(f.read())# languages.txt를 콘솔에서 출력한다.

1-4 readlines()

  • 파일의 모든 데이터를 읽어서 리스트 형태로 반환한다.
  • 파일 내용을 줄 단위로 읽어와 리스트에 저장한다.
#간단 예제
with open(uri + 'lans.txt', 'r') as f:
    lanList = f.readlines()# 모든것을 읽어서 리스트로 반환

print(f'lanList: {lanList}')
print(f'lanList type: {type(lanList)}')

readline()

  • 한 행을 읽어서 문자열로 반환 한다.
  • 각 호출마다 파일의 다음 줄을 읽어오므로, 반복적으로 호출하여 파일의 모든 줄을 읽어온다.

0개의 댓글