객체 지향 프로그래밍의 개념
절차 지향 프로그래밍과 객체 지향 프로그래밍의 장단점
절차 지향 언어 | 객체 지향 언어 | |
장점 | - 코드의 실행 속도가 빠르다 - 컴퓨터 구조에 대한 이해가 있으면 빠르게 동작하도록 최적화를 할 수 있다 |
- 코드 재사용이 용이하다 - 유지 보수가 쉽다 - 대형 프로젝트를 관리하기에 적합하다 |
단점 | - 유지 보수가 어렵다 - 직관적인 코드 분석이 어렵다 - 대형 프로젝트를 하기에는 문법적 편의성이 좋지 못하다 |
- 코드의 실행 속도가 상대적으로 느리다 - 초기에 좋게 설계하기가 어려유며 많은 시간이 투자된다 |
클래스의 개념과 정의
객체
- 객체 자체가 가질 수 있는 정보와 그러한 정보를 기반으로 객체가 수행할 수 있는 행동을 통해 정의
- 정보(속성)와 행동(메서드/함수)을 정의할 수 있게 해주는 일종의 틀 = 클래스(class)
- 클래스를 설계하고 클래스를 통해 객체를 만드는 작업을 통해 객체 지향 프로그램을 완성할 수 있다
클래스의 정의
- 서로 관련이 깊은 정보와 행동을 같이 묶을 수 있는 수단을 제공하는 일종의 설계도
class 클래스 이름:
클래스 내용
클래스 구성
생성자 메소드
- 객체가 생성할 때 호출되는 함수로 객체에 필요한 정보를 초기화하는 역할
- __init__이라는 이름의 메소드를 클래스 내부에 정의해야함
- 생성자 메소드의 첫 번째 파라미터로 self라는 값을 받고, 필요한 변수를 생성하여 정보를 초기화할 수 있다
class Car:
def __init__(self, type, speed):
self.type = type
self.speed = speed
c = Car('자동차', 100)
내부 메소드
- 클래스에 정의된 모든 메소드는 첫 번째 파라미터로 self 값을 가짐
- 실제로 메소드를 호출할 때는 self 값 자동으로 전달되므로
- 메소드가 호출될 때 메소드 내부에서 self 값을 통해 내부 변수나 메소드에 접근 가능
class Car:
def __init__(self, type, speed):
self.tyep = type
self.speed = speed
def move(self):
print("{}가 {} 속도로 움직입니다".format(self.tyep, self.speed))
def speed_up(self, amount):
self.speed += amount
c = Car('자동차', 100)
c.speed_up(10) # speed = 110
c.move # 자동차가 110 속도로 움직입니다
클래스 변수와 클래스 메소드
클래스 변수와 메소드 정의 형식
- 코든 객체가 공유해아 할 공통 변수나 메소드를 선언해야할 때 클래스 변수와 클래스 메서드 사용
- 클래스 이름을 정의한 후 콜론 다음 줄부터 정의된 변수는 모두 클래스 변수가 된다
- 클래스 메소드는 @classmethod 키워드르 쓰고 정의
- 첫 번째 인자로는 반드시 이름인 cls인 클래스 정보를 담은 변수를 받도록 해야 함
class 클래스 이름:
[클래스 변수 정의]
@classmethod
def 클래스 이름(cls, 추가 파라미터들):
[클래스 메소드 정의]
클래스 변수와 메소드 정의 예시
class Car:
count = 0
def __init__(self, type, speed):
self.tyep = type
self.speed = speed
Car.count += 1
@classmethod
def get_count(cls):
return cls.count
print(Car.get_count()) # 0
c1 = Car('자동차', 100)
c2 = Car('트럭', 80)
print(Car.get_count()) # 2
클래스의 상속
클래스 상속 정의 형식
- class 선언문에서 클래스의 이름 오른쪽에 괄호를 치고 상속을 받은 클래스의 이름 작성
- 상속받는 클래스의 생성자 메소드 내부에서 super 함수를 이용해 직접 상위 클래스 생성자 메소드 호출해야 함
# 클래스 상속 정의 형식
class 클래스 이름(상속 받을 클래스의 이름):
[추가적으로 필욯안 클래스의 내용]
def __init __(self):
super().__init__()
클래스 상속 코드 작성 예시
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self, food):
print('{}가 {}를 먹습니다'.format(self.name, food))
def __str__(self):
return self.name + '는 ' + srt(self.age) + '살 입니다.'
class Employee(Person):
def __init__(self, name, age, salary):
super().__init__(name, age)
self.salary = salary
def get_salary(self):
return self.salary
e = Employee('영희', 19 100)
print(3)
e.eat('밥')
re = get_salary()
print("급료는 " + str(re) + "만 원입니다")
+ __str__메소드는 객체를 문자열로 출력할 때 필요한 메소드로, 객체와 관련된 정보를 보여주는 역할
특수 메소드
객체 삭제와 __del__ 메소드
- 생성자 메소드로 사용되는 __init__메소드와 대비되는 용도로 사용
- del 명령어를 통해 명시적으로 객체를 삭제 가능
- __del__메서드는 객체가 삭제되기 전에 처리해야 할 해동을 정의하기 위해 사용
class DeleteClass:
def __del__(self):
print('delete') # 객체 삭제 전 delete 출력
d = DeleteClass()
del d # 객체 삭제
사용자 재정의 메소드
- __str__ : 객체와 관련된 정보를 포함하고 있는 문자열을 반환하는 메소드
- __len__ : len 함수의 파라미터로 객체 전달 시 반환 받을 숫자를 정의
- __getitem__ : 대괄호 안의 첨자를 통해 객체에 접근 시 첨자로 전달되는 키(key) 값에 따라 대응되는 적잘한 값을 반환
class Person:
def __init__(self, name, age, height):
self.name = name
self.age = age
self.height = height
def __str__(self):
return '이름 : {}, 나이 : {}'.format(self.name, self.age)
def __len__(self):
return self.height
def __getitem__(self, key):
if key == 'name':
return self.name
elif key == 'age':
return self.age
else
return None
p = Person('철수', 17, 170)
print(p) # 이름 : 철수, 나이 : 17
print(len(p)) # 170
print(p['age']) # 17
print(p['???']) # None
예외 처리의 개요
예외
- 수행이 불가능한 코드를 실행했을 때 파이썬에서 발생시키는 경고 메시지
자주 발생하는 예외
예외 클래스 | 예외 설명 |
ZeroDivisionError | 숫자를 0으로 나눌 때 발생 |
NameError | 선언되지 않은 변수에 접근하려 할 때 발생 |
TypeError | 자료형과 관련된 문제 상황이 있을 때 발생 |
IOError | 입출력과 관련된 문제 상황이 있을 때 발생 |
ValueError | 잘못된 입력 밧이 전달되었을 때 발생 |
IndexError | 리스트 요소에 잘못 접근하였을 때 발생 |
기초 예외 처리
try-except 불록 구문
- try 블록 내부에 에러가 발생할 여지가 있는 코드들 작성
- except 블록 내부에 특정 에러가 발생했을 때 사용자에게 적절한 대응책을 제공할 수 있는 코드를 작성
try :
예외가 발생할 수 있는 코드
except:
발생한 예외에 적절하게 대응할 수 있는 코드
1. try 블록 내부의 코드를 순차적으로 실행
2. 1단계에서 예외가 발생하지 않으면 except 블록 내부의 구문을 실행하지 않고 정상적으로 모든 코드가 실행
3. 만약 1단계에서 내부 코드를 실행하던 도중 예외가 발생하면 예외가 발생한 코드 이후에 실행되어야 할 코드를 실행하지 않고 except 블록 내부에 정의된 구문을 실행
finally 블록 구문
- 예외 발생 여부와 상관 없이 반드시 실행되어야 하는 코드들 작성할 때 사용
f = open('file.txt', 'w')
try:
f.write("Hello World")
f.write(100) # 타입 예외 발생
except TypeError:
print('타입 예외 발생')
finally:
print('예외 여부 상관 없이 무조건 실행')
f.close()
다양한 방식의 예외 처리
as 키워드 활용
- except 예외 클래스의 이름 as 예외 객체의 이름
- 예외 객체를 받아와 문제 상황에 대한 구체적인 힌트 얻을 수 있음
arr = [1, 2, 3]
try:
print(arr[4]) # IndexError
except IndexError e:
print(e) # list index out of range
else 키워드 활용
- try 절에 있는 블록을 실행하며 전체 코드들 실행한 후 예외가 발생하지 않았을 때 실행
arr = [1, 2, 3]
try:
print(arr[0])
print(arr[1])
print(arr[2])
except:
print('예외 발생')
else:
print('성공적으로 모든 코드 실행됨')
사용자 정의 예외
사용자 정의 예외 작성
- 파이썬에서는 프로그래머가 필요한 예외를 직접 작성할 수 있도록 허용
- Exception 클래스를 상속받은 클래스를 정의하여 사용자 예외 작성 가능
# 사용자 정의 예외 예제1
class Error(Exception):
pass
# 사용자 정의 예외 예제2
# 문제 상황에 대한 설명과 관련 메시지를 설정하고 싶을 때 생성자를 정의하여 사용
class MyError(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
raise 구문을 통한 예외 발생
- 사용자가 정의한 에러를 활용하려면 상황에 따라 적절하게 프로그래머가 raise 구문을 호출해 예외 발생시켜야 함
- raise 에러 클래스 이름
class NotEvenError(Exception):
pass
def even_number_add(a, b):
if(a%2 != 0 or b%2 != 0):
raise NotEvenError
return a + b
try:
a = even_number_add(2, 2)
b = even_number_add(3, 2) # raise의 NotEvenError 예외 발생
except NotEvenError as e:
print('짝수만 더할 수 있습니다')
파일 처리의 개요
파일
- 의미 있는 정보를 담기 위한 논리적 단위
파일 처리
- 파일과 관련된 클래스와 함수를 통하여 파일을 조작하는 행위
- 파이썬에서는 파일을 다루는 데 필요한 다양한 클래수와 함수를 제공
- 디렉터리와 관련된 모듈인 os 모듈을 제공
import os
data = os.listdir('.') # listdir - 현재 디렉터리에 있는 파일과 디렉터리의 목록을 리스트 형태로 저장
print(data) # ['file.txt', 'file1.png', 'myfolder']
for d in data:
print(d)
print('is directory? :' + str(os.path.isdir(d)))
print('is file? :' + str(os.path.isfile(d)))
# file.txt
# is directory? : False
# is file? : True
# file1.png
# is directory? : False
# is file? : True
# myfolder
# is directory? : True
# is file? : False
파일의 경로 지정
상대 경로 지정
- 현재 스크립트가 실행되는 폴더를 기주능로 위치를 표시하는 방법
- '.'으로 시작
./hello.txt
(현재 실행 폴더에 존재하는 hello.txt 문서)
./subfolder/hello.txt
(현재 실행 폴더의 하위 폴더인 subfolder에 존재하는 hello.txt 문서)
절대 경로 지정
- 최상위 디렉터리부터 시작하는 경로를 지정하는 것
- 드라이브 명과 파일이 존재하는 하위 디렉터리의 이름을 모두 명시하여 경로로 지정
c:/hello.txt
(C 드라이브의 hello.txt 문서)
c:/subfolder/hello.txt
(C 드라이브의 하위 폴더인 subfolder에 존재하는 hello.txt 문서)
텍스트 데이터 저장
텍스트 파일 생성과 데이터 저장
- 파일에 내용을 기록하기 전에 먼저 파일을 열어야함
- open(file_name, access_mode)
- open 함수에서는 파일의 이름과 어떤 접근 방식(access mode)로 파일을 열 것인지 두 가지 인자를 받아들여 파일 열음
- 한글을 입력하려면 open 함수에서 encoding 값을 지정해야함 (encoding = 'utf8')
file_name | 파일의 경로를 문자열로 지정하며, 절대 경로, 상대 경로를 모두 사용 가능 |
access_mode | 파일에 접근하는 방법을 문자열로 지정 r : 텍스트를 읽기 위해 파일 열음 / 읽기 전용 방식이라 내용을 쓸 수 없음 w : 텍스트를 저장하기 위해 파일 열음 / 만약 파일이 존재하지 않으면 파일을 새로 생성하고 열음 + w로 파일 열면 이전 내용 없어지고 새로 텍스트 저장됨 rb : 이진 데이터를 읽기 위한 용도 wb : 이진 데이터를 저장하기 위한 용도 a : 기존에 존재하던 파일에 내용을 이어 붙일(append) 용도로 파일 열음(쓰기) |
f = open('hangul.txt', 'w', encoding='utf8')
f.write('한글')
f.write('\nEnglish')
f.close()
이진 데이터 저장
이진(binary) 파일 생성과 데이터 저장
- 이진 데이터를 저장하는 최소단위 : 바이트 (1바이트 : 0~255 범위의 값 저장 가능)
# 리스트에 저장된 10진수 값을 파일에 바이트 형태로 저장
f = open('data.bin', 'wb')
byte_arr = bytes([255, 0, 127])
f.write(byte_arr)
f.close()
객체 직렬화
- 객체 자체를 통째로 파일에 저장
- 객체를 파일에 저장할 수 있는 수단(pickle 모듈)을 제공
import pickle # 객체 자체를 통째로 파일에 저장
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(str):
return ('이름 : ' + self.name + '\n나이 : ' + str(self.age))
f = open('person_data.bin', 'wb')
p = Person('철수', 20)
pickle.dump(p, f) # dump - p변수의 내용(객체)을 파일f에 저장
f.close()
# pickle 내부에서 객체를 저장할 때 텍스트가 아닌 이진 데이터 형태로 변환하여 저장 = 객체 직렬화(scerialize)
# 이진 파일 내용은 HxD와 같은 16진수 편집기를 이용해야 이진 데이터의 내용을 확인할 수 있음
텍스트 데이터 읽기
텍스트 파일을 통해 데이터 읽기 예제
# 파일 쓰기
f = open('text.txt', 'w', encoding='utf8')
f.write('안녕하세요.')
f.write('\n')
f.write('반갑습니다.')
f.close()
# 파일 읽기 : read()
f = open('text.txt', 'r', encoding='utf8')
# 파일에 저장된 텍스트 모두 읽고 출력
str = f.read()
print(str)
f.close()
# 파일 읽기 : readline()
f = open('text.txt', 'r', encoding='utf8')
# 파일에 저장된 텍스트 한 줄씩 읽기
line1 = f.readline()
print('line1 :', line1)
line2 = f.readline()
print('line2 :', line2)
line3 = f.readline()
print('line3 :', line3)
f.close()
# line1 : 안녕하세요.
#
# line2 : 반갑습니다.
# line3 :
# line1과 line2 사이에 '\n' 문자도 읽고 출력
# line3은 내용 없어서 빈 문자열 출력
이진 데이터 읽기
이진 파일을 통해 데이터 읽기
import array
f = open('data.bin', 'wb')
byte_arr[]
for i in range(0, 256):
byte_arr.append(i)
data = bytes(byte_arr)
f.write(data)
f.close()
f = open('data.bin', 'rb')
data = array.arry('B')
data.fromfile(f, 10)
for item in data:
print(item, end=', ')
f.close()
객체 역직렬화
import pickle
class Person:
pass
# load 메소드에 전달하여 한 사람의 정보가 담긴 객체를 얻어와 출력
f = open('person_data.bin', 'rb')
person = pickle.load(f)
print(person)
f.close()
# load 메소드에 전달하여 여러 사람의 정보가 담긴 객체를 얻어와 출력
f = open('persons_data.bin', 'rb')
person = pickle.load(f)
for p in person:
print(p)
f.close()
'전공' 카테고리의 다른 글
파이썬_모듈, 패키지 (2) | 2024.12.19 |
---|---|
자료구조_알고리즘 (1) | 2024.12.17 |
Java_예외 처리, 스레드 (0) | 2024.10.08 |
Java_컬렉션 제네릭 (7) | 2024.10.08 |
파이썬_변수, 자료형 / 제어문, 반복문 / 함수 (0) | 2024.07.10 |