220907 Day11

유예지·2022년 9월 7일

6. 파일 입출력

(1) 파일 생성하기

  • 구조: 파일 객체 = open("파일이름", '파일열기모드')
  • 파일 열기 모드
    -w : write 쓰기모드
    -r : read 읽기모드
    -a : append 추가
    -b : binary (음악, 사진, 동영상)
    -wb : binary 쓰기 모드

* 파이썬에서는 모든 것이 '객체'이다. 함수 또한 '객체'가 될 수 있다

>>> f = open("new.txt", 'w')   #파일 객체(f)를 만들고
    f.write("Hello\n")   #메서드를 사용하고 ("Hello"를 파일 객체 f에 써라)
    f.close()   #닫아준다

#f.write()는 print()와 동일하게 data를 출력하지만, 모니터 화면 대신 '파일'에 결괏값을 적는 방법이다.

>>> f = open("new.txt", 'a')   #파일열기모드가 'a'
	f.write("Good morning\n")
	f.close()
    
>>> f = open("new.txt", 'w')
	f.write("Hello\n")
	f.write("Good morning\n")
	f.write("Good afternoon")
 	f.close()
>>> f = open("new.txt",'w')
	for i in range(10):
	    f.write(f"{i}\n")
	f.close()
    
>>> f = open("new.txt",'w')
	for i in range(10):
	    f.write("Hello\n")
	f.close()

>>> f = open("new.txt",'a')
	for _ in range(10):
	    f.write("Good morning\n")
	f.close()    

* with문 - with open() as f:

-f.close()를 자동으로 처리해준다
-with 블록을 벗어나는 순간, 열린 파일 객체 f가 자동으로 close 된다

>>> f = open("new.txt", 'w')
	f.write("Hello\n")
	f.close()
    
>>> with open("new.txt", 'w') as f:
	    f.write("Hi\n")   #f는 객체
        
>>> with open("new.txt", 'a') as f:
	    for _ in range(10):
	        f.write("Good\n")      

(2) 파일 읽기

-파이썬에서는 외부 파일을 읽어들여 프로그램에서 사용할 수 있는 여러가지 방법이 있다.

* f.readline()

-파일의 첫번째 줄을 읽어 출력한다

>>> with open("new.txt", 'w') as f:
	    f.write("Hello\n")
        
>>> with open("new.txt", 'r') as f:   #파일읽기모드가 'r'
	    data = f.readline()
	    print(data)
    
#input()으로 데이터를 직접 입력받아 출력하는 방법과 비교하면,
input()은 '키보드를 사용한' 입력방법이고, f.readline()은 "파일을 사용한" 입력방법이다.        

* f.readlines()

-파일의 모든 줄을 읽어서 각각의 줄을 요소로 갖는 "리스트" 로 출력한다

>>> f = open("new.txt", 'w')
	for _ in range(5):
	    f.write("Hello.\n")
	f.write("Good morning.\n")
	f.write("Good afternoon.")
	f.close()
    
>>> f = open("new.txt", 'r')
	data = f.readlines()
	print(data)
	f.close()    
    
>>> f = open("new.txt", 'r')
	data = f.readlines()
	for i in data:
	    print(i, end = " ")
	f.close()    

* f.read()

-파일의 내용 전체를 "문자열" 로 돌려준다

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

* 연습문제

>>> f = open("test.txt", 'w')
	for i in range(10):
	    print(f"{i+1}번째 입니다.")
        
>>> with open("test.txt", 'w', encoding = 'UTF-8') as f:
	    for i in range(10):
	        f.write(f"{i+1}번째 입니다.\n")     
  • readlines로 읽기
>>> with open("test.txt", 'r', encoding = 'UTF-8') as f:
	    data = f.readlines()
	    for i in data:
	        print(i, end=" ")
            
>>> with open("test.txt", 'r', encoding = 'UTF-8') as f:
	    data = f.readlines()
	    for i in data:
	        i = i.strip()
	        print(i)
  • 함수 : show_file("파일이름") 만들기
>>> def show_file(filename):
	    with open(filename, 'r', encoding = 'UTF-8') as f:
	        data = f.readlines()
	        for i in data:
	            i = i.strip()
	            print(i)
>>> show_file("test.txt")                
  • 이름과 나이를 입력받아 people.txt 파일 만들기
>>> f = open("people.txt", 'w', encoding = 'UTF-8')
	while True:
	    name = input("이름: ")
		if name == "":
		    break
	    age = input("나이: ")
	    f.write(f"{name} : {age}\n")
	f.close()
>>> show_file("people.txt")

7. Class 클래스

-같은 성격을 갖고 있는 것끼리 한 반(class)에 모아놓은 것
-80% 정도 만들어 놓는 것

-class 클래스 : 똑같은 무엇인가를 계속해서 만들어 낼 수 있는 설계 도면(과자 틀)
-object 객체 : 클래스로 만든 피조물(과자 틀을 사용해 만든 과자)

-동일한 클래스로 만든 객체들은 서로 전혀 영향을 주지 않으며, 객체마다 고유한 성격을 가진다
-1개의 클래스는 무수히 많은 객체를 만들어 낼 수 있다

* "+" 기능을 가지고 있는 기계를 만들어보자

>>> result = 0

	def add(num):
        global result
    #add 함수 안에서 함수 밖의 result 변수를 직접 사용하겠다
    #'이전에 계산한 결괏값을 유지하기 위해서' result 전역변수(global)을 사용했다
        result += num
        return result

    add(3)
3

>>> add(4)
7

* 같은 기능을 하는 기계가 '2대' 필요하다면

-각 계산기는 각각의 결괏값을 유지해야하기 때문에 add 함수 하나만으로는 결괏값을 따로 유지할 수 없다 -> 함수를 각각 따로 만들어야 한다

>>> result1 = 0
    result2 = 0

    def add1(num):
        global result1
        result1 += num
        return result1

    def add2(num):
        global result2
        result2 += num
        return result2
        
>>> add1(5)
5
>>> add1(6)
11
#같은 기능을 하는 기계가 3대 필요하다
>>> result1 = 0
    result2 = 0
    result3 = 0

    def add1(num):
        global result1
        result1 += num
        return result1

    #추가
    def subtract1(num):
        global result1
        result1 -= num
        return result1

    def add2(num):
        global result2
        result2 += num
        return result2

    #추가
    def subtract2(num):
        global result2
        result2 -= num
        return result2

    def add3(num):
        global result3
        result3 += num
        return result3

    #추가
    def subtract3(num):
        global result3
        result3 -= num
        return result3
#같은부분이 계속 반복되고 있다 -> 수정 또는 추가를 하려면 그만큼 같은 과정을 여러번 반복해야한다

>>> add3(5)
5
>>> subtract(3)
2

(1) 클래스의 필요성

* 클래스는 '설계도' 이다

>>> class Calculator:   #클래스의 이름은 '대문자'로 시작해야한다
        def __init__(self):
#언더바 2개 : 특별한 의미를 준다는 것 / 함수의 인자값에는 항상 'self'를 입력한다
            self.result = 0
#변수 앞에 항상 'self'를 함께 입력한다 / 초기값을 0으로 설정

        def add(self, num):
            self.result += num
            return self.result

        def subtract(self, num):
            self.result -= num
            return self.result
            
#설계도로 인해 구체물로 만들어지는 과정
>>> pos = Calculator()           

#'pos.' 입력하고 tab키를 누르면 생성된 function들을 확인할 수 있다.
>>> pos.add(7)
7
>>> pos.subtract(3)
4

* pos기 1대 더 만들기

>>> pos1 = Calculator()
>>> pos2 = Calculator()
>>> pos3 = Calculator()

#수정 또는 추가를 하고 싶다면
>>> class Calculator:
        def __init__(self):
            self.result = 0

        def add(self, num):
            self.result += num
            return self.result

        def subtract(self, num):
            self.result -= num
            return self.result

        def multiply(self, num):
            self.result *= num
            return self.result
            
>>> pos = Calculator()

(2) 클래스 만들기

* 객체 = object, instance

-객체변수는 그 객체의 고유한 값을 저장할 수 있는 공간이다
-객체변수는 다른 객체들의 영향을 받지 않고 독립적으로 그 값을 유지한다

-모든 객체는 2가지의 형태를 갖고 있다 -> 동사, 형용사
-동사 : method 메서드
-형용사 : attribute 속성
-예)
car.동사 -> car.go(), car.back(), car.turn()
car.형용사 -> car.color, car.size
bird.동사 -> bird.fly(), bird.sing()
bird.형용사 -> bird.color

* 사칙연산 클래스 만들기

>>> class FourCal:
		pass
        
>>> class FourCal:   #클래스 안에 들어가있는 함수 -> '메서드'
		def setdata(self, a, b):
        	self.first = a
            self.second = b
    #setdata 메서드는 매개변수로 'self, a, b' 3개의 입력값을 받는다
            
>>> cal = FourCal()   #cal 이라는 객체를 만들고
>>> cal.setdata(1, 2)   #cal 객체를 통해 setdata 메서드를 호출했다
#setdata 메서드의 첫번째 매개변수 self에는 setdata 메서드를 호출한
객체 cal이 자동으로 전달된다

>>> cal.first
1
>>> cal.second
2

-파이썬 메서드의 첫번째 매개변수 이름은 관례적으로 'self'를 사용한다
-이는 객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self를 사용한 것이다

>>> class FourCal:
        def setdata(self, a, b):
            self.first = a
            self.second = b

        def add(self):   #add 메서드가 새로 추가되었다
            self.result = self.first + self.second
            return self.result
        #add 메서드의 매개변수는 self 이고, 반환값은 result 이다

        def subtract(self):
            self.result = self.first - self.second
            return self.result
            
>>> cal = FourCal()
>>> cal.setdata(1, 2)   #cal 객체의 a, b 변수에는 각각 1과 2가 저장된다
	cal.first
1
>>> cal.add()   #add 메서드 호출
3
>>> cal.subtract()
-1

>>> cal1 = FourCal()   #추가로 객체 1개를 더 정의했다
>>> cal1.add()
	cal1.subtract()
AttributeError: 'FourCal' object has no attribute 'first'
#setdata 메서드를 수행해야 객체 cal1의 매개변수 a와 b가 생성될 수 있기 때문

>>> cal1.setdata(10, 30)
>>> cal1.add()
40

* __init__() : 생성자(constructor); 초기화시키는 함수

-없으면 만들어서라도 실행될 수 있게 해준다
-즉, setdata()함수를 먼저 실행하지 않아도 되게 해준다
-모든 클래스는 생성자를 갖고 있다

-객체에 '초깃값을 설정' 해야할 필요가 있을 때는 setdata와 같은 메서드를 호출하여 초깃값을 설정하기 보다는 "생성자"를 구현하는 것이 안전한 방법이다
-constructor 생성자 : 객체가 생성될 때 자동으로 호출되는 메서드
-메서드 이름으로 __init__ 를 사용하면 이 메서드는 생성자가 된다

>>> class FourCal:
        def __init__(self, a, b):   #setdata 대신에 __init__를 넣었다
            self.first = a
            self.second = b
        #__init__ 메서드가 호출되면 setdata 메서드를 호출했을 때와 마찬가지로
        a와 b라는 객체변수가 생성될 것이다
        
        def add(self):
            self.result = self.first + self.second
            return self.result

        def subtract(self):
            self.result = self.first - self.second
            return self.result
            
>>> cal2 = FourCal(1, 2)
>>> cal2.add()
3

>>> cal3 = FourCal(10, 20)
	cal3.subtract()
-10

#메서드 이름을 __init__ 로 하면 생성자로 인식되어 객체가 생성되는 시점에 자동으로 호출되기 때문에, setdata 메서드를 호출하여 매개변수 a, b에 해당하는 값을 전달하는 과정을 거치지 않아도 된다
#객체를 생성하면서 매개변수에 해당하는 값을 전달해주면 된다

* 사칙연산이 가능한 함수를 만들어보자

>>> class FourCal:
        def __init__(self, a, b):
            self.first = a
            self.second = b

        def add(self):
            self.result = self.first + self.second
            return self.result

        def subtract(self):
            self.result = self.first - self.second
            return self.result

        def multiply(self):
            self.result = self.first * self.second
            return self.result

        def divide(self):
            self.result = self.first / self.second
            return self.result
            
>>> cal = FourCal(1, 0)
>>> cal.multiply()
0
>>> cal.divide()
ZeroDivisionError: division by zero   #0으로 나누기가 안된다

>>> cal = FourCal(1, 2)
>>> cal.divide()
0.5

(3) 클래스의 상속

-어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 하는 것
-기존 클래스는 그대로 나둔 채 클래스의 기능을 확장시킬 때 주로 사용한다
-기존 클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않는 상황이라면 상속을 사용해야 한다

>>> class Child(FourCal):
		pass
#Child 클래스는 FourCal 클래스를 상속했으므로, FourCal 클래스의 모든 기능을 사용할 수 있어야 한다    

>>> cal = Child(10, 20)
>>> cal.add()
30
>>> cal.multiply()
200

#메서드 추가
>>> class Child(FourCal):
        def power(self):
            self.result = self.first ** self.second
            return self.result
            
>>> cal = Child(2, 3)
>>> cal.power()
8
#cal 함수는 상속받은 메서드 '+,-,*,/'에 추가로 '**'까지 수행할 수 있다

>>> cal = Child(1, 0)
>>> cal.power()
1
>>> cal.divide()
ZeroDivisionError: division by zero

* method overriding 메서드 오버라이딩 : 메서드 재정의

-부모 클래스(상속한 클래스)에 있는 메서드를 동일한 이름으로 다시 만드는 것
-메서드 오버라이딩을 하면 부모 클래스의 메서드 대신 오버라이딩한 메서드가 호출된다

>>> class Child(FourCal):
        def power(self):
            self.result = self.first ** self.second
            return self.result

        def divide(self):
            if self.second != 0:
                self.result = self.first / self.second
                return self.result
            else:
                print("0으로 나누셨군요")
                
>>> cal = Child(1, 0)
>>> cal.divide()
0으로 나누셨군요
#새로 업데이트된 함수가 적용된다 (메서드를 새로 만들어서 덮어쓰기 한 셈이다)

>>> class Calculator():
        def __init__(self, a, b):
            self.first = a
            self.second = b
            
>>> cal = Calculator(1, 2)
>>> cal.first   #self.first에 해당하는 값을 부른다 (즉 cal = self 로 볼 수 있다)
1

>>> bal = Calculator(10, 20)
>>> bal.first   #self : '객체'를 지칭하는 말
10

0개의 댓글