개발/Python

Python 클래스 속성 vs 인스턴스 속성 (멤버 변수 고찰)

신매력 2020. 10. 15. 00:00

파이썬은 C언어나 Java에 비해 제약이 없는 언어이다.

파이썬은 변수의 타입 명시도 없고, 값을 변경할 수 없는 상수의 개념도 없다.

 

C언어나 Java는 미성년자를 대하는 것과 같다.

이러면 안되고 저러면 안되는 법칙이 명확히 주어진다. 한마디로 제약이 많다.

 

반면 파이썬은 성인을 대하는 것과 같다.

"자유는 주겠지만 네가 알아서 잘써라"

 

 

이번에 파이썬으로 클래스를 만들면서 이상한점을 발견했다.

class GradeCard:
    scores = list()

    def add_score(self, score):
        self.scores.append(score)


t1 = GradeCard()
t2 = GradeCard()
t1.add_score(100)
t2.add_score(80)

print("t1:", t1.scores)
print("t2", t2.scores)

 

GradeCard라는 클래스의 인스턴스인 t1, t2 객체 두 개를 만들어서

각각의 객체의 scores 리스트에 점수 하나를 추가했다.

 

예상한 결과는 아래와 같았지만

t1: [100]

t2: [80]

 

실제 결과는 아래와 같았다.

t1: [100, 80]

t2: [100, 80]

 

각 객체의 멤버변수인줄 알았던 scores는 같은 클래스의 객체들이 공유를 하고 있었던 것이다.

 

 

각 객체가 각자 다른 변수를 갖기 원한다면 

생성자에서 멤버변수를(변수 앞에 self를 붙여서) 세팅해주어야 한다.

 

class GradeCard:
    def __init__(self):
        self.scores = list()

    def add_score(self, score):
        self.scores.append(score)


t1 = GradeCard()
t2 = GradeCard()
t1.add_score(100)
t2.add_score(80)

print("t1:", t1.scores)
print("t2", t2.scores)


결과>>

t1: [100]

t2: [80]

 

 

다른 언어에서는 클래스 밑에 멤버변수를 선언해놓지만

파이썬에서는 멤버변수를 선언하려면 생성자에서 선언해야한다.

 

파이썬에서 클래스 밑에 멤버변수를 쓰는 것은 클래스의 상수로 사용할 때이다.

 

class Math:
    pi = 3.141592


print(Math.pi)


결과>>

3.141592

 

인스턴스화를 하지 않아도 클래스의 상수처럼 사용할 수 있다.

(파이썬에선 상수 개념이 없으므로 수정도 가능하지만 본인이 알아서 잘써야 한다.)

 

 

파이썬은 굳이 문법의 제한을 해두지 않는다.

그래서 객체의 멤버변수 선언을 클래스 밖에서도 할 수 있다.

 

class GradeCard:
    scores = list()

    def add_score(self, score):
        self.scores.append(score)


t1 = GradeCard()
t1.name = "신매력"

print(t1.name)

결과>>

신매력

 

이렇게도 가능하지만 별로 좋은 방법은 아닌 것 같다.

 

 

 

 

 

문법적으로 허용되는게 많다보니 파이썬의 철학을 이해하기가 어려운 부분이 있다.