Study Web Development

3월 23일

이전으로

Python

6. 클래스

@classmethod

  1. 새 파일 s10_class10.py 생성
class Car:
    cnt = 0
    count = 0 # 특정 객체에 소속되지 않으며 이 클래스로부터 생성되는 모든 객체가 공유
    def __init__(self,name):
        self.name = name
        self.cnt += 1 # 객체 생성시마다 0으로 초기화되는 객체 자신의 변수를 호출
        Car.count += 1 # 모든 객체가 공유하는 클래스 변수를 호출
    def printcnt(self):
        print(self.cnt)
    @classmethod
    def outcount(cls):
        print(cls.count)

# 객체 생성
pride = Car('프라이드')
pride.printcnt()
Car.outcount()
print('-'*3)

korando = Car('코란도')
korando.printcnt()
Car.outcount()
print('-'*3)

sonata = Car('소나타')
sonata.printcnt()
Car.outcount()
print('-'*3)

예외 처리

try~except

  1. 새 PyDev Project ch07-exception 생성하고 새 파일 s01_exception.py 생성
# 예외 처리 try~except
try:
    a = 'hello'
    print(a)
    print(a[10]) # 없는 인덱스를 호출하여 인위적으로 예외 발생
    print(a)
except:
    print('error 발생')
print('-'*3)

try:
    a = 'hello'
    print(a)
    print(a[10])
    print(a)
except IndexError: # 발생하는 예외 객체를 명시 가능
    print('error 발생')
print('-'*3)

try:
    a = 'hello'
    print(a)
    print(a[10])
    print(a)
except Exception: # 발생하는 예외 객체의 상위 예외 객체를 명시 가능
    print('error 발생')
  1. 새 파일 s02_exception2.py 생성
def divide(a,b):
    return a/b

# try~except
try:
    c = divide(5,'string')
    print(c)
except ZeroDivisionError:
    print('두 번째 인자는 0이면 안 됩니다')
except TypeError:
    print('모든 인자는 숫자여야 합니다')
except:
    print('error 발생')
  1. 새 파일 s03_exception3.py 생성
def divide(a,b):
    return a/b

try:
    c = divide(5, 'apple')
    print(c)
except Exception: # 모든 예외를 여기서 처리하게 됨; Java와 달리 상위 예외 객체를 먼저 명시해도 동작은 하지만 이후의 except 블럭이 무의미해짐
    print('무슨 에러인지 모르겠어요')
except ZeroDivisionError:
    print('0으로 나누면 안 돼요')
except TypeError:
    print('숫자만 나눌 수 있어요')
  1. 새 파일 s06_exception6.py 생성
def divide(a,b):
    return a/b

try:
    c = divide(5, 0)
    print(c)
except (ZeroDivisionError,OverflowError): # 명시된 에러를 모두 처리
    print('수치 연산 관련 에러입니다')
except TypeError:
    print('숫자만 나눌 수 있습니다')
except Exception:
    print('error 발생')

else, finally

  1. 새 파일 s04_exception4.py 생성
def divide(a,b):
	return a/b

try:
	c = divide(5,2)
except ZeroDivisionError:
	print('0으로 나눌 수 없습니다')
except TypeError:
	print('숫자만 나눌 수 있습니다')
except:
	print('ZeroDivisionError, TypeError를 제외한 다른 에러')
else: # 예외가 발생하지 않는 경우
	print('Result: {0}'.format(c))
finally: # 예외가 발생하건 발생하지 않건 항상 수행
	print('항상 수행됩니다')

예외 정보 전달

  1. 새 파일 s05_exception5.py 생성
def divide(a,b):
    return a/b

try:
    c = divide(5, 'string')
    print(c)
except TypeError as e: # 전달되는 예외 객체를 e로 받아서 사용
    print(type(e.args))
    print('에러:',e.args[0])
except Exception:
    print('error 발생')

raise

  1. 새 파일 s07_exception7.py 생성
def RaiseErrorFunction():
    raise NameError('NameError의 인자') # 내장 예외인 NameError를 발생

try:
    RaiseErrorFunction()
except NameError as e:
    print(e.args[0])
    print('NameError is caught')
  1. 새 파일 s08_exception8.py 생성
# 사용자 정의 예외 클래스
class NegativeDivisionError(Exception): # Exception을 상속
    # 생성자
    def __init__(self,value):
        self.value = value

def PositiveDivide(a,b):
    if b<0: # b가 0보다 작은 경우 사용자 정의 예외를 발생시킴
        raise NegativeDivisionError(b)
    return a/b

try:
    a = int(input('첫 번째 수: '))
    b = int(input('두 번째 수: '))
    result = PositiveDivide(a,b)
    print('{1} / {2} = {0}'.format(result,a,b))
except NegativeDivisionError as e:
    print('Error: 두 번째 인자',e.value)
except ZeroDivisionError as e:
    print('Error:',e.args[0])
except: # 그 외의 모든 예외
    print('Error 발생')

5. 함수

파일 읽고 쓰기

.txt
옵션 값 파일 모드 의미
r 읽기 모드 파일을 읽을 때 사용
w 쓰기 모드 파일에 데이터를 저장할 때 사용
a 추가 모드 기존의 파일에 데이터를 추가할 때 사용
  1. 새 PyDev Project ch08-io 생성하고 새 파일 s01_file.py 생성
# 파일 모드를 지정하여 파일 열기
f = open('new_file.txt','w',encoding='UTF-8')

# 리스트에서 데이터를 읽어들여 파일에 기재
names = ['바닐리치', '바닐프티', '배바닐라']
for name in names:
    f.write(name+'\n')
print('파일 쓰기 완료')

# 파일 닫기
f.close()
  1. 새 파일 s02_file2.py 생성
# 기존 파일에 데이터를 추가
f = open('new_file.txt','a',encoding='UTF-8')

names = ['불켜미', '샹델라']
for name in names:
    f.write(name+'\n')
print('파일에 데이터 추가 완료')

f.close()
  1. 새 파일 s03_file3.py 생성
# 파일로부터 데이터 읽기
# readlines(): 전체 내용을 읽어서 행들의 리스트로 반환
f = open('new_file.txt','r',encoding='UTF-8')
lines = f.readlines()
print(lines)
print('-'*3)
for line in lines:
    temp = line.replace('\n','') # print()가 기본적으로 줄바꿈처리하므로 불필요한 \n 제거
    print(temp)
f.close()
print('-'*3)

# 영역 내에서 작업
with open('new_file.txt','r',encoding='UTF-8') as f:
    for line in f.readlines():
        print(line.replace('\n',''))
f.close()
print('-'*3)

# read(): 파일의 전체 내용을 읽어서 문자열로 반환
f = open('new_file.txt','r',encoding='UTF-8')
lines = f.read()
print(lines)
f.close()
  1. 새 파일 s04_file4.py 생성
# 파일 생성
f = open('text2.txt','w',encoding='UTF-8')
# write(): 작성한 문자 수를 반환
print(f.write('오늘은 수요일\n도로롱 도로롱'))
f.close()

# 파일 모드를 지정하지 않으면 읽기 모드
f = open('text2.txt',encoding='UTF-8')
print(f.read())
f.close()
  1. 새 파일 scores.txt 생성하여 읽어올 데이터를 임의로 넣고 새 파일 s05_file5.py 생성
# scores.txt 파일 읽기
f = open('scores.txt',encoding='UTF-8')
lines = f.readlines()
print(lines)
print('-'*3)

for line in lines:
    data = line.split() # 구분자를 지정하지 않으면 공백(\s, \t, \n) 기준으로 문자열을 잘라냄
    # print(data)
    i=0
    sum=0
    
    while i<len(data):
        if i==0: # 인덱스 0은 이름
            print(data[i],end=': ') # 줄바꿈하지 않음
        else:
            sum+=int(data[i])
        i+=1
    
    avg=sum/(len(data)-1) # 길이에서 이름을 제외해야 과목 수
    print('%.2f점' % avg)

f.close()

정규표현식

  1. 새 PyDev Project ch09-regncsv 생성하고 새 파일 s01_regexp.py 생성
# 정규표현식 사용
import re

sentence = 'I have a lovely cat, really. I am not telling a lie. What a pretty cat! I love this cat.'

# re.split(): 특정한 패턴이 등장할 때 문자열을 나눔
# r'[.?!]'에서 r을 쓰면 역슬래시를 붙이지 않아도 마침표, 느낌표, 물음표를 특수문자가 아닌 일반 문자로 인식
result = re.split(r'[.?!]', sentence)
print(result)
print('-'*3)

data = 'a:3;b:4;c:5'
for i in re.split(r';',data):
    print(re.split(r':',i))
print('-'*3)

# sub(): 문자열 바꾸기
data2 = re.sub(r'cat',r'rabbit',sentence)
print(data2)
print('-'*3)

words = 'I am home now. \n\nI am with my cat.\n\n'
print(words)
print('-'*3)
data3 = re.sub(r'\n','',words)
print(data3)
print('-'*3)

# findall(): 패턴을 문자열에서 모두 찾아서 리스트로 반환
sentence = 'I have a lovely cat, really. I am not telling a lie'
# \w: 문자나 숫자가 몇 번 나와도 좋으니 반복하고(+), ly로 끝나는 패턴을 의미
words2 = re.findall(r'\w+ly', sentence)
print(words2)

다음으로