파이썬과 객체지향 프로그래밍 - 한발짝 깊게 들어가는 클래스 속성과 메서드

7. 한발짝 깊게 들어가는 클래스 속성과 메서드

7.1. 클래스 변수와 인스턴스 변수 (attribute를 한 단계 더 구분해보자)

  • 클래스 변수: 클래스 정의에서 메서드 밖에 존재하는 변수
    • 해당 클래스를 사용하는 모두에게 공용으로 사용되는 변수
    • 클래스 변수는 클래스 내외부에서 "클래스명.변수명" 으로 엑세스 가능
  • 인스턴스 변수: 클래스 정의에서 메서드 안에서 사용되면서 "self.변수명"처럼 사용되는 변수
    • 각 객체별로 서로 다른 값을 가짐
    • 클래스 내부에서는 self.인스턴스변수명 을 사용하여 엑세스, 클래스 밖에서는 객체명.인스턴스변수명 으로 엑세스
In [207]:
class Figure:
    count = 0  # 클래스 변수
 
    # 생성자(initializer)
    def __init__(self, width, height):
        # self.* : 인스턴스변수
        self.width = width
        self.height = height
        # 클래스 변수 접근 예
        Figure.count += 1
    
    def __del__(self):
        Figure.count -= 1
    
    # 메서드
    def calc_area(self):
        return self.width * self.height
In [201]:
figure1 = Figure(2, 3)
Figure.count
figure2 = Figure(2, 3)
Figure.count
Out[201]:
2
초간단 연습9
* 다음 코드를 실행시키면서, 출력 값이 왜 이렇게 나왔는지 이해하기(클래스 변수와 인스턴스 변수 이해)
In [208]:
print(Figure.count)
figure1 = Figure(2, 3)
print(Figure.count)
figure2 = Figure(4, 5)
print(Figure.count)
print(figure1.width)
print(figure2.width)
del figure1
print(Figure.count)
del figure2
print(Figure.count)
0
1
2
2
4
1
0

7.2. instance method, static method, class method (현재는 들어만 보면 됨) (심화)

instance method: 해당 객체 안에서 호출 (지금까지 다룬 self.메서드명을 의미함)

  • 해당 메서드를 호출한 객체에만 영향을 미침
  • 객체 속성에 접근 가능

static method: 객체와 독립적이지만, 로직상 클래스내에 포함되는 메서드

  • self 파라미터를 갖고 있지 않음
  • 객체 속성에 접근 불가
  • 정적 메서드는 메서드 앞에 @staticmethod 라는 Decorator를 넣어야 함
  • 클래스명.정적메서드명 또는 객체명.정적메서드명 둘 다 호출 가능
In [84]:
class Figure:
    # 생성자(initializer)
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    # 메서드
    def calc_area(self):
        return self.width * self.height

    # 정적 메서드 (Figure 에 너비와 높이가 같은 도형은 정사각형임을 알려주는 기능)
    @staticmethod
    def is_square(rect_width, rect_height):
        if rect_width == rect_height:
            print("정사각형이 될 수 있는 너비/높이입니다.")
        else:
            print("정사각형이 될 수 없는 너비/높이입니다.")
In [85]:
figure1 = Figure(2, 3)
figure1.is_square(5, 5)         # 객체명.정적메서드명으로 호출 가능
Figure.is_square(4, 5)          # 클래스명.정적메서드명으로 호출 가능
정사각형이 될 수 있는 너비/높이입니다.
정사각형이 될 수 없는 너비/높이입니다.


한발짝 더 나가보기!(심화 문제)
아래 코드를 실행시키면서 특이 값과 에러를 확인하고, 출력 값이 왜 이렇게 나왔는지 이해하기(정적/인스턴스 메서드 이해)
In [89]:
class Figure:
    count = 0  # 클래스 변수

    # 생성자(initializer)
    def __init__(self, width, height):
        # self.* : 인스턴스변수
        self.width = width
        self.height = height
        # 클래스 변수 접근 예
        Figure.count += 1
        
    # 정적 메서드 (정적 메서드에서는 클래스 attribute 는 접근 가능)
    @staticmethod
    def print_count():
        print(Figure.count)

    # 정적 메서드 (에러: 정적 메서드에서는 객체 attribute 는 접근 불가)
    @staticmethod
    def print_width():
        print(self.width)
In [90]:
figure1 = Figure(1, 2)
print(Figure.count)
print(figure1.print_count())
print(figure1.print_width())
1
1
None
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-90-07d5e35f53ce> in <module>()
      2 print(Figure.count)
      3 print(figure1.print_count())
----> 4 print(figure1.print_width())

<ipython-input-89-e28fbca90349> in print_width()
     18     @staticmethod
     19     def print_width():
---> 20         print(self.width)

NameError: name 'self' is not defined

class method: 해당 class 안에서 호출 (해당 클래스로 만들어진 객체에서 호출되지 않고, 직접 클래스 자체에서 호출)

  • self 파라미터 대신, cls 파라미터를 가짐
  • 클래스 변수 접근 가능하며 cls.클래스변수명 으로 엑세스 가능 단, 객체 속성/메서드는 접근 불가
  • 클래스 메서드는 메서드 앞에 @classmethod 라는 Decorator를 넣어야 함
  • 클래스명.클래스메서드명 또는 객체명.클래스메서드명 둘 다 호출 가능
In [92]:
class Figure1:
    count = 0  # 클래스 변수
 
    # 생성자(initializer)
    def __init__(self, width, height):
        # self.* : 인스턴스변수
        self.width = width
        self.height = height
        # 클래스 변수 접근 예
        Figure1.count += 1
    
    # 메서드
    def calc_area(self):
        return self.width * self.height

    # 클래스 메서드
    @classmethod
    def print_count(cls):
        return cls.count

figure1 = Figure1(2, 3)
figure2 = Figure1(4, 5)
print(Figure1.count)
print(Figure1.print_count()) # 2
print(figure1.print_count()) # 2
2
2
2
한발짝 더 나가보기!(심화 문제)
아래 코드를 실행시키면서 실행 결과를 확인하고, 출력 값이 왜 이렇게 나왔는지 이해하기(클래스 메서드 이해)
In [15]:
class A(object):
    count = 0 # static member (class variable)
    
    def __init__(self, cnt):
        A.count += 1
        self.cnt = cnt # member variable, attribute
        
    def print_cnt(self): # memeber function, method
        print(self.cnt)
        
    @classmethod # class method, static function
    def print_count(cls):
        print(cls.count)
        
a1 = A(1)
a2 = A(2)
a3 = A(44)

a1.print_cnt()
a2.print_cnt()
a3.print_cnt()

A.print_count()
1
2
44
3