[Python] 클래스 (Class)


Study/Python  2019. 12. 17. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 클래스에 관한 글입니다.


먼저 클래스에 대한 개념을 소개해야 하는데, 다른 프로그램 언어를 다루어 본 적이 있는 분이라면 대충 클래스의 개념을 알고 있을 꺼라 생각됩니다.

python는 스크립트 언어이기 때문에 굳이 클래스를 몰라도 프로그래밍을 하는 데는 지장이 없습니다.


그러나 사용하는 데이터를 여러개의 변수로 늘어 놓는 것보다 하나의 개념의 구분을 묶어 놓는 것이 관리적으로 편하고 프로그램을 설계하는 데 있어도 이해하기 편합니다.


예를 하나 작성해서 클래스를 사용하는 것과 사용하지 않는 것의 차이를 비교하겠습니다.

# 학급 반의 이름과 국영수의 점수를 입력하고, 학생의 평균과 반 평균을 구하여라.
# 사람 이름
person = [];
# 국어 점수 리스트
korean = [];
# 수학 점수 리스트
math = []
# 영어 점수 리스트
english = [];

# 사람을 추가
def add_person(name, k, m, e):
  global person;
  global korean;
  global math;
  global english;
  person.append(name);
  korean.append(k);
  math.append(m);
  english.append(e);

# 평균 구하는 함수
def calculate_average(index):
  global person;
  global korean;
  global math;
  global english;
  return int((korean[index] + math[index] + english[index]) / 3);

# 전체 평균 구하는 함수
def calculate_total_average():
  global person;
  global korean;
  global math;
  global english;
  i = 0;
  sum = 0;
  while i < len(person):
    sum += calculate_average(i);
    i += 1;
  return sum / len(person);

# a, b, c, d, e 사람을 추가하였다.
add_person('a', 50, 60, 80);
add_person('b', 40, 80, 60);
add_person('c', 80, 70, 30);
add_person('d', 80, 60, 80);
add_person('e', 90, 80, 90);

# 각 평균을 구하고 전체 평균을 구하였다.
print(calculate_average(0));
print(calculate_average(1));
print(calculate_average(2));
print(calculate_average(3));
print(calculate_average(4));
print(calculate_total_average());

위 처럼 python 식을 작성해도 각 반 인원의 평균값이 구해지고 전체 평균 값도 구할 수 있습니다. 그러나 만약 국어 점수 리스트에서 하나의 데이터를 빼거나 추가하게 되면 각 리스트의 총 개수가 달라져 버그가 발생할 수 있겠네요.

그리고 예를 들면 english의 리스트만 보았을 때 누구의 점수인지 구분하기 어려워 집니다. 즉, person 리스트가 초기화 되던가 없어지면 전체 데이터 밸런스가 망가지게 됩니다.


그럼 클래스는 어떨까요?

# Person이라는 클래스를 만들었다.
class Person():
  # 생성자에서는 name과 korean, math, english의 값을 받는다.
  def __init__(self, name, korean, math, english):
    self.__name = name;
    self.__korean = korean;
    self.__math = math;
    self.__english = english;
  # 평균을 구한다.
  def calculate_average(self):
    return int((self.__korean + self.__math + self.__english)/3);
    
person_list = [];
# person_list에 Person클래스로 a, b, c, d, e의 사람을 추가하였다.
person_list.append(Person('a', 50, 60, 80));
person_list.append(Person('b', 40, 80, 60));
person_list.append(Person('c', 80, 70, 30));
person_list.append(Person('d', 80, 60, 80));
person_list.append(Person('e', 90, 80, 90));

# 각 인원의 평균을 구한다.
for p in person_list:
  print(p.calculate_average());

# 전체의 평균을 구한다.
sum = 0;
for p in person_list:
  sum += p.calculate_average();  
print(sum / len(person_list));

소스 양만 보더라도 클래스를 사용하기 전과 후는 확연히 줄어 들었습니다. 그리고 각 인원의 점수를 각각의 korean이나 math등의 리스트에 저장한 것과 다르게, Class 내부의 변수에 담아서 클래스 안에 국어, 수학, 영어 점수를 보관하고 있습니다.

즉, person_list에서 하나의 값을 빼더라도 그 인원의 국어, 영어, 수학 점수도 같이 빠지기 때문에 계산의 무결성에서는 문제가 없습니다.


Python에서 클래스를 선언하는 방법은 class 키워드에 클래스 명을 선언하면 됩니다. 소괄호는 나중에 상속을 위한 것으로 다음에 설명을 하겠습니다.

Python의 클래스는 메서드로 이루어져 있습니다. 다른 언어처럼 따로 변수를 선언할 수가 없고, 각 함수의 첫번째 파리미터는 self로 고정입니다.

__init__의 함수는 초기화 함수로 보통 생성자라고 합니다. 생성자는 없어도 클래스를 만드는 데는 문제는 없습니다만, 가독성을 위해 생성해 놓는 것이 좋습니다.


각 함수의 self는 자기 자신의 클래스를 가르키는 것입니다.

전역 변수를 사용하려면 self.변수명으로 접근이 가능합니다.


변수명을 선언할 때는 변수명 앞에 언더바(_)를 두개 붙여야 합니다. 그렇지 않으면 외부에서 접근이 가능한 public 형태로 변수가 지정이 되기 때문에 반드시 언더바(_)두개를 붙여서 private로 선언해야 합니다.

class ClassExample():
  def __init__(self):
    self.var = "test1";
    self.__var = "test2";

cls = ClassExample();
# 언더바를 붙이히 않으면 public으로 참조가 되어 버립니다.
print(cls.var);
# 참조 불가능..
print(cls.__var);

이건 객체 지향의 캡슐화와 관계가 있는 구조로 클래스의 변수가 외부에서 직접 참조가 되어 버리면, 클래스의 의미가 없어지게 됩니다. 클래스 내부의 변수로 함수를 이용해 여러가지 작업을 하게 됩니다만, 외부에서 접근이 가능하게 되면 클래스의 구조의 의미가 없어집니다.


클래스를 생성(인스턴스)하는 방법은 변수 = 클래스명();으로 호출을 하면 됩니다. 다른 언어와 다르게 따로 new 키워드가 필요없습니다.

뒤 괄호의 의미는 __init__에서 self 파라미터를 뺀 나머지 파라미터의 초기화입니다.


함수의 호출 방법은 생성된 변수에서 함수를 호출하면 됩니다. 반대로 클래스명.함수명(인스턴스) 형식으로도 선언이 가능합니다.

class ClassExample():
  def __init__(self):
    # 아무런 처리가 없을 때는 pass; 키워드를 사용한다.
    pass;
  def print(self):
    print("Hello world");

cls = ClassExample();
# 개인적으로 이런 방법이 더 편합니다.
cls.print();
# 이런 방법은 생소합니다.
ClassExample.print(cls);

여기까지 Python에서 클래스에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.