본문 바로가기
Programming/Python

22. 클래스의 추가적인 구문

by IT learning 2021. 3. 27.
728x90

오늘은 클래스의 추가적인 구문들을 소개하겠다.

 

클래스를 사용하는 것은 작정하고 속성과 기능을 가진 객체를 만들겠다라는 의미다.

따라서 부가적인 기능 또한 제공하고 있다.

어떤 클래스를 기반으로 그 속성과 기능을 물려받아 새로운 클래스를 만드는 상속, 이러한 상속 관계에 따라서 객체가 어떤 클래스를 기반으로 만들었는지 확인할 수 있게 해주는 isinstance() , 파이썬이 기본적으로 제공하는 str() 함수 등등이 대표적인 예이다.

 

어떤 클래스의 인스턴스인지 확인하기

객체(인스턴스)가 어떤 클래스로부터 만들어졌는지 확인할 수 있도록 isinstance() 함수를 제공한다.

isinstance(인스턴스, 클래스)

첫 번째 매개변수에 객체(인스턴스), 두번째 매개변수에 클래스를 입력한다.

이때 인스턴스 해당 클래스를 기반으로 만들어졌다면 True, 전혀 상관이 없는 인스턴스와 클래스 라면 False를 리턴한다.

# isinstance() 함수 활용

# 학생 클래스를 선언합니다.
class Student:
    def study(self):
        print("공부를 합니다.")
        
# 선생님 클래스를 선언합니다.
class Teacher:
    def teach(self):
        print("학생을 가르칩니다.")
        

# 교실 내부의 객체 리스트를 생성합니다.
classroom = [Student(), Student(), Teacher(), Student(), Student()]


# 반복을 적용해서 적절한 함수를 호출하게 됩니다.
for person in classroom:
    if isinstance(person, Student):
        person.study()
    elif isinstance(person, Teacher):
        person.teach()

위 코드를 보자.

Student 클래스와 Teacher 클래스를 각각 만들어, classroom 이라는 리스트를 만들어 내부에 객체들을 넣었다.

반복을 적용했을때 반복할때마다 isinstance() 함수를 활용하여 나오는 요소들이 Student 클래스 인지, Teacher 클래스인지를 구분하여 각각의 출력을 하는 프로그램이다.

위 코드의 실행결과이다.

일반적으로 객체 지향 프로그래밍은 모든 데이터를 클래스로 구현한다.

 

 

특수한 이름의 메소드

이름들이 특이한 메소드들이 있다. __<이름>__() 형태로 되어있다.

이러한 메소드는 특수한 상황에 자동으로 호출되도록 만들어졌다.

 

먼저 __str__() 을 사용해보겠다.

# __str__() 함수

# 클래스를 선언합니다.
class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
    
    def get_sum(self):
        return self.korean + self.math + self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(
            self.name,
            self.get_sum(),
            self.get_average()
        )
    
    
# 학생 리스트를 선언합니다.
students = [
    Student("1", 87, 98, 88, 95),
    Student("2", 92, 98, 96, 98),
    Student("3", 76, 96, 96, 95),
    Student("4", 55, 66, 77, 88)
]


# 츌력합니다.
print("이름", "총점", "평균", sep="\t")
for student in students:
    print(str(student)) # str 함수의 매개변수로 넣으면 student의 __str__() 함수가 호출됩니다.

위 코드를 살펴보자.

다음과 같이 __str__()을 클래스 내부에 정의해 보았다.

이렇게 내부에 함수를 정의하면 str() 함수를 호출할 때 __str__() 함수가 자동으로 호출된다.

위 코드의 실행결과이다.

따라서 이전의 to_string() 함수가 아니라 str(객체)라는 지금까지 사용했던 것과 같은 방법으로 객체를 문자열로 변환할 수 있다.

 

몇 가지 특이한 이름을 정리해보자면.

이름 영어 설명
eq equal 같다
ne not equal 다르다
gt greater than 크다
ge greater than or equal 크거나 같다
lt less then 작다
le less then or equal 작거나 같다

위 메소드들을 사용하여 성적을 비교할 수 있는 코드를 작성할 수 있다.

# 크기 비교 함수

class Student:
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
    
    def get_sum(self):
        return self.korean + self.math + self.english + self.science
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(
            self.name,
            self.get_sum(),
            self.get_average()
        )
    
    def __eq__(self, value):
        return self.get_sum() == value.get_sum()
    def __ne__(self, value):
        return self.get_sum() != value.get_sum()
    def __gt__(self, value):
        return self.get_sum() > value.get_sum()
    def __ge__(self, value):
        return self.get_sum() >= value.get_sum()
    def __lt__(self, value):
        return self.get_sum() < value.get_sum()
    def __le__(self, value):
        return self.get_sum() <= value.get_sum()
    
    
students = [
    Student("1", 87, 98, 88, 95),
    Student("2", 92, 98, 96, 98),
    Student("3", 76, 96, 96, 95),
    Student("4", 55, 66, 77, 88)
]


# 학생을 선언합니다.
student_a = Student("1", 87, 98, 88, 95),
student_b = Student("2", 92, 98, 96, 98),

print("student_a == student_b = ", student_a == student_b)
print("student_a != student_b = ", student_a != student_b)
print("student_a >  student_b = ", student_a > student_b)
print("student_a >= student_b = ", student_a >= student_b)
print("student_a <  student_b = ", student_a < student_b)
print("student_a <= student_b = ", student_a <= student_b)

위 코드의 실행결과이다.

 

클래스 변수와 메소드

인스턴스가 속성과 기능을 가질 수도 있지만, 클래스가 속성(변수)과 기능(함수)를 가질 수도 있다.

 

클래스 변수

클래스 변수 만드는 방법은 다음과 같다.

class 클래스 이름:
	클래스 변수 = 값

class 구문 바로 아래의 단계에 변수를 선언하기만 하면 된다.

변수에 접근하는 방법은

클래스이름.변수이름

위와 같은 식으로 접근하면 된다.

 

클래스 변수로 학생의 생성 수를 알아볼 수 있는 코드를 작성해보았다.

# 클래스 변수

class Student:
    count = 0
    
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
        
        Student.count += 1
        print("{}번째 학생이 생성되었습니다.".format(Student.count))
        
students = [
    Student("1", 87, 98, 88, 95),
    Student("2", 92, 98, 96, 98),
    Student("3", 76, 96, 96, 95),
    Student("4", 55, 66, 77, 88)
]

print()
print("현재 생성된 총 학생의 수는 {}명입니다.".format(Student.count))

# 클래스 내부와 외부에서 클래스 변수에 접근할 때는 모두 Student.count 형태 (클래스이름.변수이름)를 사용합니다.

클래스 내부에 변수를 생성하고 사용하면 되는 간단한 방법의 사용이다.

위 코드의 실행결과이다.

 

클래스 함수

클래스 함수도 클래스 변수처럼 그냥 클래스가 가진 함수이다.

그런데 생성하는 방법이 조금 특이하다. @classmethod 부분을 데코레이터 라고 부른다.

예전에 했던 함수 데코레이터클래스 데코레이터의 기능은 같다.

만드는 법은

class 클래스 이름:
	@classmethod
    def 클래스 함수(cls,매개변수):
    	pass

클래스 함수의 첫 번째 매개변수에는 클래스 자체가 들어온다.

일반적으로 cls 라는 이름의 변수로 선언하며, 이렇게 만들어진 클래스 함수는 다음과 같이 사용한다.

클래스 이름.함수 이름(매개변수)

그럼 클래스 함수를 사용해 보자.

student라는 학생 리스트를 아예 클래스 내부에 만들어 버리고 학생 리스트를 전부 출력하는 Student.print() 함수를 만들어봤다.

# 클래스 함수

class Student:
    count = 0
    students = []
    
    @classmethod
    def print(cls):
        print("-------- 학생 목록 --------")
        print("이름", "총점", "평균", sep="\t")
        for student in cls.students:
            print(str(student))
        print("------ ------ ------ ------")
        
    def __init__(self, name, korean, math, english, science):
        self.name = name
        self.korean = korean
        self.math = math
        self.english = english
        self.science = science
        Student.count += 1
        Student.students.append(self)
    
    
    def get_sum(self):
        return self.korean + self.math + self.english + self.science
    
    
    def get_average(self):
        return self.get_sum() / 4
    
    def __str__(self):
        return "{}\t{}\t{}".format(
            self.name,
            self.get_sum(),
            self.get_average()
        )
    
    
Student("1", 87, 98, 88, 95)
Student("2", 92, 98, 96, 98)
Student("3", 76, 96, 96, 95)
Student("4", 55, 66, 77, 88)

Student.print()

중간에 print() 함수에서 반복문을 돌릴때의 조건이 cls.students 라고 나와있다.

사실 Student.students라고 해도 상관은 없지만, 여기서는 매개변수로 받은 cls 를 활용한다.

위 코드의 실행결과이다.

 

오늘은 클래스의 추가적인 구문에 대해 알아보았다.

자동으로 해당 기능이 필요할때 알아서 활용이 되는 것을 보고 파이썬이란 언어는

정말 사용자에게 쉽게 만들어진 언어란것을 또 한번 느꼈다.

728x90

댓글

IT_learning's Commit