[Python]문법 총 정리(3) - 파일 입출력,함수,클래스,예외 처리

Date:     Updated:

카테고리:

1. 파일 입출력

Definition

  • 일반적으로 표준 입출력을 사용하는 프로그램은 키보드로부터 입력을 받아 모니터로 결과를 보냄
  • 프로그램이 종료된 이후에도 데이터를 저장하기 위해서 파일 입출력을 사용할 수 있다.
  • 파일 객체를 만든 때는 open(), 객체를 닫을 때는 close()
f = open('example.txt', "w")
f.close()
  • 파이썬에서눈 여러 가지 파일 모드(mode)를 제공한다,.
    • r : 읽기(Read) 모드(파일 읽기)
    • w : 쓰기(Write)모드(파일에 내용물 쓰기)
    • a : 추가(Append)모드(파일의 마지막에 새로운 내용 추가)

파일 출력, write() 함수

  • 파일의 데이터를 쓸 때는 write() 함수를 사용할 수 있다.
  • 줄바꿈 기호(\n)을 사용하여, 줄을 변결할 수 있다.
  • 여러 줄에 걸쳐서 파일에 데이터를 작설할 수 있다.
file_1 = open("result.txt", "w")
for line in range(1,6):
  data = f"{line}번째 줄\n"
  f.write(data)
f.close()

파일 읽기, readline(), strip(), read()

  • readline() 함수를 이용하면 파이르이 데이터를 한 줄씩 읽을 수 있다.
  • 각 줄을 출력할 때 줄의 마지맞에 줄바꿈 기호도 함께 포함된다
    • strip()함수를 사용하지 않으면, 두 줄씩 줄바꿈이 수행된다.

[Input]

f = open("result.txt", "r")
while True:
  line = f.readline()
  if not line: # 더 읽을 문장이 없다면  
    break
  else:
    print(line.strip())
f.close()

[Output]

1번째 줄
2번째 줄
3번째 줄
4번째 줄
5번째 줄
  • 파일의 모든 줄을 한꺼번에 읽을 떄는 readlines() 함수를 사용할 수 있다.
  • readlines() 함수는 기본적으로 각 줄을 그대로 읽기 때문에 줄바꿈 기호(\n)가 포함된다.
  • 줄바꿈 기호를 제거하기 위해 strip()을 사용할 수 있다.
    • strip() 함수를 사용하지 않으면, 두 줄씩 줄바꿈이 수행된다.

[Input]

# f를 data.txt파일로 열고 내용 입력
f = open("data.txt", 'w')
f.write("안녕하세요.\n")
f.write("반갑습니다.\n")
f.write("행복하세요~!\n")
f.close()

f =  open("data.txt", "r")
lines = f.readlines()
for i in range(len(lines)):
  line = lines[i].strip()
  print(f"{i}번째 줄의 내용: {line}")
f.close()

[Output]

0번째 줄의 내용: 안녕하세요.
1번째 줄의 내용: 반갑습니다.
2번째 줄의 내용: 행복하세요~!
  • read() 함수를 사용하면 파일의 전체 내용을 하나의 문자열로 반환한다.

[Input]

f = open("data.txt", 'r')
data = f.read()
print(data)
f.close()

[Output]

안녕하세요.
반갑습니다.
행복하세요~!

파일 객체 자동으로 열고 닫기, open(), close() 함수

  • 다음의 문법을 활용하여 파일 객체를 자동으로 여닫을 수 있다.
  • open(), close() 함수의 기능이 함께 사용된다.
with open(파일 이름, 파일 열기 모드)as f:
  파일 객체 f를 이용하는 코드
file_name = "output.txt"
with open(file_name, 'w') as f:
  f.write("Hello World")

2. 함수의 이해와 활용

Definition

  • 전체 소스코드를 기능별로 분리하여 작성하는 것이 효율적
  • 함수를 이영해 소스 코드를 기능별로 분리할 수 있음
  • def문을 사용
def add(a,b,c):
  result = a + b + c
  return result
  
print(add(3,1,5))
-> 9

Example 1) MaxIndex

  • 리스트 내 원소 중에서 가장 큰 값의 인덱스를 리턴 ```python def find_max_index(arr): max_index = 0 for i in range(len(arr)): if arr[max_index]<arr[i]: max_index = i return max_index

data = [7,1,5,9,3,2,4] max_index = find_max_index(data) print(max_index) -> 3


### Example 2) find_certain_value
- 특정한 값을 가지는 원소의 인덱스를 찾는 함수
```python
def find_certain_value:
  for i,x in enumerate(arr):
    if x == value:
      return i
  return -1 # 찾지 못한 경우 -1을 리턴
print(find_certain_value([3,5,7,9]),2)
-> -1
print(find_certain_value([3,5,7,9]),7)
-> 2

Example 3) is_prime_number

def is_prime_number(x):
  # 1이하인 경우 소수가 아님
  if x<=1:
    return False
  
  # 1과 자기 자신 외의 자연수로 나누어 떨어지는 경우 소수가 아님
  for divisor in range(2,x):
    if x % divisor == 0:
      return False
  return True

print(is_prime_number(1))  # False
print(is_prime_number(2))  # True
print(is_prime_number(3))  # True
print(is_prime_number(4))  # False
print(is_prime_number(5))  # True
print(is_prime_number(7))  # True
print(is_prime_number(10)) # False
print(is_prime_number(13)) # True
print(is_prime_number(15)) # False
print(is_prime_number(17)) # True

3. 클래스의 이해와 활용

Definition

  • 클래스는 딥러닝 프로그램 작성시 자주 사용됨
    • 클래스: 붕어빵 틀에 비유할 수 있다.
    • 인스턴스: 붕어빵 틀에서 생성된 붕어빵

Example 1) class Human

  • 사람의 정보를 담는 클래스
  • 프로그램 내에서 두 명의 사람을 처리한다면>
    • 각 사람은 나이가 다를 수 있다.
class Human():
  def __init__(self):
    self.age = 0
  
  def old(self):
    self.age += 1
    
human1 = Human() # 사람 인스턴스 생성
human2 = Human() # 사람 인스턴스 생성

for i in range(10): # 10세
  human1.old()
for i in range(20): # 20세
  human2.old()
  
# 각 사람의 나이 출력
print(human1.old)
-> 10
print(human2.old)
-> 20
  • 클래스(class)는 여러 정보를 하나의 객체에 담을 때 사용

Example 2) class Student

  • 학생 관리 프로그램을 만들때, 학생에 대한 정보는 다양하다.
    1. 학번
    2. 이름
    3. 나이
    4. 성별
    5. 학과
  • 학생 인스턴스를 생성함과 동시에 정보를 초기화할 수 있다.
    • 생성자: 인스턴스가 생성될 때 자동으로 실행되는 init()매서드를 의미한다.
  • self는 인스턴스(Instance) 자기 자신을 의미한다.
  • 해당 인스턴스가 가지는 값과 함수의 인자 값을 구분하여 이해해야 한다.
  • init() 함수 내부
    • self.name: 현재 인스턴스의 name 변수
    • name: 함수의 파라미터로 넘어 온 name 변수

[Input]

class Student:
    def __init__(self, id, name, age, gender, department):
        self.id = id
        self.name = name
        self.age = age
        self.gender = gender
        self.department = department

    def show(self):
        print("===== 학생 정보 =====")
        print(f"학번: {self.id}")
        print(f"이름: {self.name}")
        print(f"나이: {self.age}")
        print(f"성별: {self.gender}")
        print(f"학과: {self.department}")

    def add_age(self, offset):
        self.age += offset


student1 = Student("20200001", "홍길동", 20, "남성", "컴퓨터공학과")
student2 = Student("20200002", "김순자", 21, "여성", "산업디자인공학과")
student3 = Student("20200003", "임꺽정", 23, "남성", "환경공학과")

student1.show()
student2.show()
student3.show()

[Output]

===== 학생 정보 =====
학번: 20200001
이름: 홍길동
나이: 20
성별: 남성
학과: 컴퓨터공학과
===== 학생 정보 =====
학번: 20200002
이름: 김순자
나이: 21
성별: 여성
학과: 산업디자인공학과
===== 학생 정보 =====
학번: 20200003
이름: 임꺽정
나이: 23
성별: 남성
학과: 환경공학과

self의 동작 방식

  • 아래와 같이 클래스의 메서드를 호출
  • 클래스의 메서드 호출
student1.add_age(5)
  • 이때, student1 -> self에 대응되고, 값 5 -> offset에 대응된다.
  • 클래스 메서드 구현
def add_age(self, offset):
  self.age += offset
student1.add_age(5)
student1.show()

# 출력
===== 학생 정보 =====
학번: 20200001
이름: 홍길동
나이: 25
성별: 남성
학과: 컴퓨터공학과

Example 3) class Client

  • 각 인스턴스의 인스턴스 변수는 서로 달다
  • 특정한 클래스(class)의 모든 인스턴스끼 공유되는 정보가 필요하다면?
  • 클래스 변수: 해당 클래스에서 전체적으로 공유되는 변수
    • Client의 클래스 변수는 Client 클래스의 네임스페이스에 존재한다.
  • 인스턴스 변수: 구체적인 하나의 인스턴스에서 사용되는 변수
    • client1의 인스턴스 변수는 client1 인스턴스의 네임스페이스에 존재한다.

[Input]

class Client:
    client_cnt = 0

    def __init__(self, id, name, age, gender, point):
        self.id = id
        self.name = name
        self.age = age
        self.gender = gender
        self.point = point
        Client.client_cnt += 1

    def show(self):
        print("===== 고객 정보 =====")
        print(f"고객 번호: {self.id}")
        print(f"이름: {self.name}")
        print(f"나이: {self.age}")
        print(f"성별: {self.gender}")
        print(f"고객 점수: {self.point}")
        print(f"현재 총 고객 수: {Client.client_cnt}")
        
    def __del__(self):
        Client.client_cnt -= 1

client1 = Client(1, "홍길동", 20, "남성", 1200)
client2 = Client(2, "김순자", 21, "여성", 300)
client3 = Client(3, "임꺽정", 23, "남성", 700)

client1.show()
client2.show()
client3.show()
print(f"[결과] 현재 총 고객 수: {Client.client_cnt}")

[Output]

===== 고객 정보 =====
고객 번호: 1
이름: 홍길동
나이: 20
성별: 남성
고객 점수: 1200
현재 총 고객 수: 3
===== 고객 정보 =====
고객 번호: 2
이름: 김순자
나이: 21
성별: 여성
고객 점수: 300
현재 총 고객 수: 3
===== 고객 정보 =====
고객 번호: 3
이름: 임꺽정
나이: 23
성별: 남성
고객 점수: 700
현재 총 고객 수: 3
[결과] 현재 총 고객 수: 3
  • 특정한 기준에 따라서 다수의 인스턴스를 정렬하고 싶을 때가 있다.
  • 예를 들어 포인트 값이 큰 순서대로 정렬
  • key 속성의 값으로 익명 함수를 넣을 수 있다.
    • 이후에 뒤집기를 수행하면, point에 대하여 내림차순 정렬이 완료된다.
key = lambda x:x.point
  • 또한 It 함수는 A가 B보다 작다는 의미를 정의할 때 사용한다. (less than)
    • It 함수를 이용하여 정렬 기능을 구현할 수 있으며, 예시는 다음과 같다.
    • 이후에 단순히 리스트에 대하여 sort() 함수를 적용하면, 정렬이 완료된다.
def __init__(self, other):
  return self.point < other.point

[Input]

class Client:
    def __init__(self, id, name, age, gender, point):
        self.id = id
        self.name = name
        self.age = age
        self.gender = gender
        self.point = point

    def show(self):
        print("===== 고객 정보 =====")
        print(f"고객 번호: {self.id}")
        print(f"이름: {self.name}")
        print(f"나이: {self.age}")
        print(f"성별: {self.gender}")
        print(f"고객 점수: {self.point}")

    def __lt__(self, other):
         return self.point < other.point

client1 = Client(1, "홍길동", 20, "남성", 1200)
client2 = Client(2, "김순자", 21, "여성", 300)
client3 = Client(3, "임꺽정", 23, "남성", 700)
client1.show()
client2.show()
client3.show()

[Output]

===== 고객 정보 =====
고객 번호: 1
이름: 홍길동
나이: 20
성별: 남성
고객 점수: 1200
===== 고객 정보 =====
고객 번호: 2
이름: 김순자
나이: 21
성별: 여성
고객 점수: 300
===== 고객 정보 =====
고객 번호: 3
이름: 임꺽정
나이: 23
성별: 남성
고객 점수: 700
  • client를 리스트화 해서 저장

[Input]

client_list = [client1, client2, client3]

result = sorted(client_list, reverse=True)
for client in result:
    client.show()

[Output]

===== 고객 정보 =====
고객 번호: 1
이름: 홍길동
나이: 20
성별: 남성
고객 점수: 1200
===== 고객 정보 =====
고객 번호: 3
이름: 임꺽정
나이: 23
성별: 남성
고객 점수: 700
===== 고객 정보 =====
고객 번호: 2
이름: 김순자
나이: 21
성별: 여성
고객 점수: 300

Class 상속(Inheritance)

  • 클래스의 상속(inheritance)은 체계적인 프로그램 개발을 위해 필요하다.
  • ex) 학교 관리 프로그램에서는 선생님(teacher)과 학생(student)에 대한 정보가 모두 활용된다.
    1. 이들은 공통적으로 이름(name), 나이(age) 등의 정보를 가지고 있다.
    2. 인적사항 정보를 출력하는 메서드를 둘 다 사용
  • 상속을 사용하여 반복적으로 사용되는 변수 매번 선언 X

[Input]

class Human:
  def __init__(self, name, age):
    self.name = name
    self.age = age
  
    def show_student(self):
        print("===== 학생 카드 =====")
        print(f"학생 번호: {self.student_id}")
        print(f"학년: {self.grade}")
        print(f"점수: {self.score}")


student = Student("홍길동", 18, 1, 2, 95)
student.show_human()
student.show_student()

[Output]

===== 인적 사항 =====
이름: 홍길동
나이: 18
===== 학생 카드 =====
학생 번호: 1
학년: 2
점수: 95
  • 실제로 딥러닝 분야에서 Pytorch 프레임워크를 사용할 때는 다양한 클래스를 상속 받아 사용할 수 있다.
  • 다양한 기능이 라이브러리 형태로 제공되기 때문에, 상속을 받아 사용하는 것이 일반적이다.
    • Generally 기본 라이브러리(부모 클래스) 직접 수정 X
    • 상황에 맞게 적절히 상속받아 사용

4. 예외 처리

Definition

  • 예외(exception)란, 코드 실행 도중에 발생하는 오류로 이해할 수 있다. 예를 들어 0으로 나누는 연산은 수행이 불가능하다.
    • ZeroDivisionError: 0으로 나누었을 때 발생하는 오류
    • 존재하지 않는 인덱스(Index) 접근 오류

try ~ except ~ 구문

  • 특정한 오류를 처리
  • 원하는 예외 이름에 대하여 처리 try ~ except ~ 구문
    try:
    기본적으로 실행할 코드
    except:
    예외가 발생했을 때 실행할 코드
    

Example 1) 존재하지 않는 인덱스에 접근

[Input]

list = [7,5,3]
index = 10

try:
  data = list[index]
  print(data)
except IndexError as e:
  print("배열의 크기를 벗어난 인덱스에 접근할 수 없습니다")
  print("[오류 메세지]")
  print(e)

[Output]

배열의 크기를 벗어난 인덱스에 접근할 수 없습니다.
[오류 메시지]
list index out of range

Example 2) 0으로 나눌떄 오류

[Input]

data_list = [1, 2, 3, 4, 5]
index = 3
x = 0

try:
    data = data_list[index]
    result = data / x
    print(result)
except IndexError as e:
    print("배열의 크기를 벗어난 인덱스에 접근할 수 없습니다.")
    print("[오류 메시지]")
    print(e)
except ZeroDivisionError as e:
    print("0으로 나눌 수 없습니다.")
    print("[오류 메시지]")
    print(e)    

[Output]

0으로 나눌  없습니다.
[오류 메시지]
division by zero
  • 딥러닝에서는 출력 차원이 일치하지 않아서 오류가 자주 발생

Reference

py 카테고리 내 다른 글 보러가기

댓글 남기기