Notice
Recent Posts
Recent Comments
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
10-11 02:09
Archives
Today
Total
관리 메뉴

Developer_Neo

[python] 클래스 및 예외처리 본문

프로그래밍/Python

[python] 클래스 및 예외처리

_Neo_ 2022. 1. 17. 11:18
반응형

클래스

- 객체를 만드는 도구

 

클래스(class)란 똑같은 무엇인가를 계속해서 만들어 낼 수 있는 설계 도면이고(과자 틀),

객체(object)란 클래스로 만든 피조물(과자 틀을 사용해 만든 과자)을 뜻한다.

출처 https://wikidocs.net/28

 

05-1 클래스

초보 개발자들에게 클래스(class)는 넘기 힘든 장벽과도 같은 존재이다. 독자들 중에도 클래스라는 단어를 처음 접하는 이들도 있을 것이다. 그러면 도대체 클래스가 무엇인지 ...

wikidocs.net

 

 

메소드만을 갖는 간단한 클래스 구조

- 메소드를 호출할 때에 self자리에는 인수를 넘기지 않는다.

class 클래스명:
	'''docstring'''
    
    def 메소드(self):
    	'''docstring'''

클래스를 만들 때 모든 메소드의 첫번째 인수는 self여야한다.

 

예제

class Dog: 

	def wag_tail(self): 
		print('The dog is wagging its tail.')
        
>>> happy = Dog( ) # happy 객체를 만듦
>>> happy.wag_tail( ) # 객체가 wag_tail( ) 메소드 호출
The dog is wagging its tail.

 

생성자 __init__(self)

- 객체를 만들 때 자동 호출이 된다.

def __init__(self, name, age): # __init__( )은 객체를 만들 때 자동 호출
	self.name = name # 만들어진 객체의 name 공간에 name값으로 초기화
	self.age = age
    
class Dog: 

	def __init__(self, name, age):
		self.name = name 
		self.age = age
        
	def introduce(self): 
		print('My name is {} and {} years old.'.format(self.name, self.age))
        
	def wag_tail(self): 
		print('{} is wagging its tail.'.format(self.name))
        
	def bark(self):  
		print('{} is barking. woof ~'.format(self.name))
        
        
x = Dog('Happy', 2) 
y = Dog('Hope', 3) 
x.introduce( ) 
y.introduce( ) 
x.bark( )  
y.bark( )  
x.wag_tail( )  
y.wag_tail( ) 

'''
결과
My name is happy and 2 years old. 
My name is hope and 3 years old. 
Happy is barking. woof ~ 
Hope is barking. woof ~ 
Happy is wagging its tail. 
Hope is wagging its tail.
'''

 

self

self는 클래스 안에 있는 모든 메소드의 첫 번째 매개 변수 자리에 넣어야 함. 생략할 수 없음

일반적으로 self 매개 변수에는 인수를 넘기지 않음.

self 매개 변수에 인수를 넘기는 경우도 있음.

 

class Dog: 

	def __init__(self, name, color): 
		self.name = name 
		self.color = color 
	def introduce(self): 
		print('나의 이름은 {}이고, {} 색이에요.'.format(self.name, self.color)) 


# self에 인수를 넘기지 않는 경우
a = Dog('Luna', 'white') 
b = Dog('Terry', 'black') 
a.introduce( ) 
b.introduce( )

# self에 인수를 넘기는 경우
a = Dog('Luna', 'white') 
b = Dog('Terry', 'black') 
Dog.introduce(a) # self 에 객체 a 넘김
Dog.introduce(b) # self 에 객체 b 넘김

 

객체 출력하기

- 그냥 객체를 인자로 주면 객체의 참조값(id)을 출력하기 때문에, 객체의 데이터 속성을 출력하려면 따로 메소드를 만들어 주어야 함 

- 클래스-> __str__, __repr__ 가 제공   둘 중 하나만 작성해도 된다.

  __str__ 이나 __repr__의 return값이 print함수의 인수가 된다 

  즉 print함수에 객체를 넣으면 알아서 __str__이나 __repr__가 호출되어 return값을 반환해 print의 인수로 들어가게 된다.

class Dog: 
	def __init__(self, name): 
		self.name = name 
		
	def __repr__(self):
    	return self.name
    
    def __str__(self):
    	return self.name
        
# main

happy=Dog('Happy')
hope=Dog('Hope')
print(happy)
print(hope)

'''
결과
Happy
Hope
'''

 

__len__, __iter__, __str__

 

__len__ 이라는 것은 len함수가 호출되었을 때 호출되는 것으로 길이를 반환한다.

 

내가 만든 클래스에 len()함수가 작동되게 하고 싶다면 이 메소드를 추가하는데 반환값은 len함수를 쓴 결과이어야한다.

 

__str__ 이라는 것은 str함수가 호출되었을 때 호출되는 것으로 문자열을 반환한다.

 

내가 만든 클래스에 str()함수가 작동되게 하고 싶다면 이 메소드를 추가하는데 반환값은 문자열로써 해주면 된다.

 

class Car:
    def __init__(self, id):
        self.id = id       # 차량 번호


    def __len__(self):
        return len(self.id)      # 차량 번호의 길이가 반환됨

    def __str__(self):
        return 'Vehicle number : ' + self.id


def main():
    c = Car("32러5234")
    print(len(c))
    print(str(c))

main()

 

__iter__라는 것은 iter함수가 호출되었을때 호출되는 것으로 iterable객체를 만들어주는 역할을 하게 된다.

 

그래서 클래스를 만들 때에 __iter__메소드를 추가하면 iterable하게 for문을 돌릴수 있게 되는데 이때의 반

 

환값에 iter함수를 써야한다. 아니면 iterable객체를 반환해주면 된다.

class Car:
    def __init__(self, id):
        self.id = id       # 차량 번호


    def __iter__(self):
        return iter(self.id)


def main():
    c = Car("32러5234")
    for i in c:
        print(i, end = ' ')
    

main()
iterable 객체  iter함수에 인자로 전달 가능한 객체이며 이 결과로 iterator객체를 반환한다.
iterator 객체 next 함수에 전달 가능한 객체

for문에 iterable객체나 iterator객체 둘다 사용가능하다.

 

iterable객체의 조건은 __iter__ 메소드가 존재해야한다.

__iter__ 메소드는 iterator객체를 반환해야하니 iter함수를 쓴 결과를 반환해야한다.

 

iterator객체의 조건은 __next__ 메소드가 존재해야한다.

 

__next__ 메소드

- next()함수 호출시 불리는 것으로 내가 만든 클래스가 iterator객체로 사용하기 위해서는 조건이 2가지가 있다.

 

  1. 가지고 있는 값을 하나씩 반환해야한다.
  2. 더이상 반환할 값이 없는 경우 StopIteration예외를 발생시켜야한다.

예를 살펴보자

class Coll:
    def __init__(self, d):
        self.ds = d
        self.cc = 0       # next 호출 횟수
        
    def __next__(self):
        if len(self.ds) <= self.cc:
            raise StopIteration

        self.cc += 1
        return self.ds[self.cc - 1]


def main():
    co = Coll([1, 2, 3, 4, 5])    # 튜플 및 문자열도 전달할 수 있음

    while True:
        try:
            i = next(co)      # iterator 객체를 통해서 하나씩 꺼낸다.
            print(i, end = ' ')
        except StopIteration:      # 더 이상 꺼낼 객체가 없으면,
            break      # 이 루프를 탈출한다.
    

main()

raise에 대한 것은 밑에서 다루겠다.

next호출 횟수에 대한 것을 0으로 두고 next함수가 호출될때마다 1씩 증가시켜 예외를 발생시키는 상황을 만들었다.

 

만약 아직 호출할 횟수가 남았다면 가지고 있는 값을 반환해주는 것으로 해야하기 때문에 return에 인덱싱을 사용해서

 

했다(인자로 받는 것은 인덱싱이 가능한 시퀀스 자료형 또는 키값이 정수인 사전만 가능할 것이다.)

 

 

iterator객체이자 iterable객체가 되게끔 해보자

class Coll2:
    def __init__(self, d):
        self.ds = d
        
    def __next__(self):
        if len(self.ds) <= self.cc:
            raise StopIteration

        self.cc += 1
        return self.ds[self.cc - 1]

    def __iter__(self):
        self.cc = 0      # next 호출 횟수 초기화
        return self      # 이 객체를 그대로 반환함


def main():
    co = Coll2([1, 2, 3, 4, 5])

    for i in co:
        print(i, end = ' ')
        
    for i in co:
        print(i, end = ' ')

main()

__iter__ 메소드에  self.cc = 0   에 해당하는 next 호출 횟수 초기화의 코드를 집어넣었는데 이유는 for문을 돌때(iter함수

 

호출됨) Coll2클래스의 객체를 인자로 넣어주면 __iter__메소드가 있는지 확인 후 돌아가게 되는데 이때에는 무조건 처음

 

부터 반목문을 돌아야 하기 때문에 0으로 해주었다.

 

또다른 하나의 예는 이것이다 

https://devloper-dreaming.tistory.com/46

 

[python] __iter__( ), __next__( )

iterable 객체 - for문과 함께 사용하여 각 데이터를 하나씩 처리할 수 있도록 하는 객체 - 우리가 클래스를 만들때 특정 메소드를 추가 하면코드 상에서 iterable객체로 만들 수 있다. __iter__( ), __next__

devloper-dreaming.tistory.com

 


예외처리

- 문법 에러 – Syntax error

- 그외 에러 – TypeError, NameError, IndexError, ValueError, KeyError, ZeroDivisionError, AttributeError, FileNotFoundError

 

문법

try:
	'''docstring'''
    
except 에러이름:
	'''docstring'''
    
except 에러이름:
	'''docstring'''

else:
	'''docstring'''
    
finally:
	'''docstring'''

- try구문 안에서 에러가 발생하면 except옆에 적은 에러이름과 일치하는 것이 있다면 거기로 간다.

- 에러이름과 일치하는 것이 없다면 에러가 발생된다.

- 만약 try블록에서 에러가 발생하지 않는 경우 else구문으로 넘어간다

- else구문은 try구문에서 에러가 없는 경우에만 수행된다.

- finally구문은 에러발생과 상관없이 무조건 수행된다.

 

 

어떤 에러든 처리하기

  1. except: 
  2. except Exception: 
a = 10 
b = 0 
try: 
c = a / b 
print(c) 
except: # except만 적음. 
print('cannot divide by zero')

'''
결과
cannot divide by zero
'''

a = int(input('Enter a : ')) 
b = int(input('Enter b : ')) 
L = [1, 3, 5] 
try: 
	c = a / b # b가 0이면 ZeroDivisionError가 발생 
	print(c) 
	L[3] = 100 # IndexError가 발생
	print(L) 
except Exception: # try 블록에서 어떤 에러가 발생하든지 예외 처리를 함
	print('Some error occured')
    
'''
결과 (IndexError가 발생한 경우)
Enter a : 5 
Enter b : 1 
5.0 
Some error occured
'''

 

except ~ as 구문

except 에러이름 as e:
	'''예외처리 문장'''

e는 변수로 에러가 발생했을 때 어떤 에러인지 e에 저장된다.

 

x = int(input('x : ')) 
y = input('y : ') 
try: 
	z = x + y # 정수 + 문자열은 TypeError가 발생합니다. 
except TypeError as e: 
	print(e) 

'''
결과
x : 5 
y : 7 
unsupported operand type(s) for +: 'int' and 'str' 
'''

 

에러가 발생했을 때, 특별히 처리할 내용이 없다면 간단히 pass로 블록을 완성할 수 있음

a = int(input('a : ')) 
b = int(input('b : ')) 
L = [4, 8, 12] 
try: 
	c = a / b # ZeroDivisionError
	v = L.index(3) # IndexError
except: 
	pass 
finally: 
	print('finally block entered')

 

프로그래머가 필요할 때 에러 발생시키기 - raise

print('start of the program') 
try: 
    print('start of try block') 
	raise ValueError # ValueError 발생시킴
	print('cannot reach this line') 
except ValueError: 
	print('exception occurred')
    
    
'''
결과
start of the program 
start of try block 
exception occurred 
'''

 

참고한 책 : 윤성우의 열혈파이썬 중급편

반응형
Comments