본문 바로가기

Programming/Python

클래스 변수와 객체 변수

저번시간 정리한 내용을 복습하고 시작하자 ( 매우 중요 하기 때문)

객체 지향 프로그래밍의 두가지 주인공
    
클래스 : 새로운 형식을 정의
객체 : 클래스의 인스턴스를 의미

ex ) int라는 형식의 변수를 만들 수 있다는 것 ,
        이는 곧 정수형을 저장하는 변수는 int 클래스의 객체(인스턴스)를 변수에 할당하는 것 이라고 말할 수 있다.

쉽게 생각하면 클래스는 뽑기 틀에 비유하고 , 인스턴스는 틀에 의해 생성되는 뽑기 들을 생각하면된다.


객체는 그 객체에 내장된 일반적인 변수들을 사용하여 데이터를 저장할 수 있다.
이 때 객체 혹은 클래스에 소속된 변수들을 필드라고 불렀다.
객체는 또한 내장된 함수를 이용하여 어떤 기능을 갖도록 하는데 이것을 클래스의 메소드 라고 불렀다.

또 이러한 필드와 메소드들을 통틀어 클래스의 속성이라고 불렀다.

클래스 변수는 클래스 자체에 내장되어 있는것이고 , 인스턴스 변수는 클래스의 인스턴스/객체에 내장되어 있는 것이다.



클래스 메소드는 일반적인 함수와 다른점이 하나 있다고 했다.
매개변수의 목록에 항상 추가로 한 개의 변수가 맨앞에 추가되어야 한다는것이다 . ( self )
또한 , 메소드를 호출할 때 이 변수에는 우리가 직접 값을 넘겨주지 않으며 , 대신 파이썬이 자동으로 값을 할당한다.

이 변수 ( self ) 에는 현재 객체 자신의 참조가 할당된다.


init 메소드는 클래스가 인스턴스화 될 때 호출되며 , 이 메소드는 객체가 생성될 때 여러가지 초기화 명령들이 필요할 때 유용하게 사용된다.



클래스 변수와 객체 변수 

앞서 , 클래스와 객체가 어떤 기능을 갖도록 하는방법 , 즉 메소드에 대해 설명했다.
이제 필드에 대해 알아보자 , 필드는 일반적인 변수와 다를것이 없으나 딱 한가지 , 그 클래스 혹은 객체의 네임스페이스
묶여 있다는 점이 다른점이다.     이것은 필드의 이름은 그 클래스 혹은 객체 내부에서만 의미가 있음을 의미한다.

그래서 이것을 이름이 통용되는 공간 , 네임스페이스라고 부른다.


클래스 변수 : 공유가능 . 즉 , 그 클래스로부터 생성된 모든 인스턴스들이 접근할 수 있다.
                  클래스 변수는 한 개만 존재하여 어떤 객체가 클래스 변수를 변경하면 모든 다른 인스턴스들에 변경 사항이 반영됨.


객체 변수 : 클래스로부터 생성된 각각의 객체/인스턴스에 속해 있는 변수.
                각각의 객체별로 객체 변수를 하나씩 따로 가지고 있으며 , 서로 공유되지 않고 각 인스턴스에 존재하는 같은 이름의
                필드끼리 서로 어떤 방식으로든 간섭되지 않는다.


아래 예시를 보자



class robot:
# 클래스 변수 population , 로봇의 수를 카운트
population = 0

def __init__(self , name):
self.name = name
print("Initializing {}".format(self.name))
robot.population += 1

def die(self):
print("{} is being destroyed".format(self.name))
robot.population -= 1

if robot.population == 0:
print("{} was the last one ".format(self.name))

else:
print("There are still {:d} robots working.".format(robot.population))


def say_hi(self):
print("Greetings , my masters call me {}.".format(self.name))

def how_many(cls):
print("We have {:d} robots.".format(cls.population))

droid1 = robot("R2-D2")
droid1.say_hi()
robot.how_many()

droid2 = robot("C-3PO")
droid2.say_hi()
robot.how_many()

print("\n Robots can do some work here. \n")

print("Robots have finished their work , so let's destory them.")
droid1.die()
droid2.die()

robot.how_many

실행 결과 :    

(Initializing R2-D2)

Greetings, my masters call me R2-D2.

We have 1 robots.

(Initializing C-3PO)

Greetings, my masters call me C-3PO.

We have 2 robots.

Robots can do some work here.

Robots have finished their work. So let's destroy them.

R2-D2 is being destroyed!

There are still 1 robots working.

C-3PO is being destroyed!

C-3PO was the last one.

We have 0 robots.


예제가 좀 길지만 , 클래스 / 객체 변수의 이해를 돕도록 했다.
여기서 population은 robot 클래스에 속해있는 클래스 변수이다.
또 , name 변수는 객체에 소속되어있는 ( 즉 self 를 이용하여 사용되는 ) 객체 변수이다.


또한 , population 클래스 변수는 robot.population과 같이 사용하며 self.populaltion과 같이 사용하지 않는다.

반면 객체 변수 name은 그 객체 안에서 self.name과 같이 사용된다.
이러한 클래스 변수와 객체 변수의 차이점을 유의하자.    또 , 클래스 변수와 같은 이름을 가진 객체 변수는 클래스 변수를 감춘다!


robot.population 대신에 self.class.population 이라고도 사용은 가능한데 이것은 모든 객체는 그 객체를 생성하는 데 사용되었던

클래스를 self.class 속성을 통해 참조하고 있기 때문이다.

메소드 how_many 는 객체에 소속되어 있지 않고 , 클래스에 소속되어 있는 메소드다.
여기서 우리가 해당 클래스의 어떤 부분까지 알아야 할 지에 따라 메소드를 클래스 메소드로 정의할지
스태틱 메소드로 정의할지 결정이 가능하다.
여기서는 클래스 변수로 사용할 것이므로 , 클래스 메소드를 사용한다.


init메소드 robot의 인스턴스를 초기화시킬 때 사용된다.
이 메소드를 통해 로봇이 하나 추가될 때마다 로봇의 개수를 의미하는 변수 population을 1씩 증가시켜 준다.

또한 각 생성된 객체별로 객체 변수 self.name의 값을 따로따로 지정해 주었다.


객체에 속해 있는 변수와 메소드에 접근하기 위해서는 반드시 self 를 사용해야 한다는 점을 기억하자.
이것을 다른말로 속성 참조 라고 부른다.


die메소드가 실행되면 , 간단히 robot.population을 하나 줄여 준다.

모든 클래스 멤버는 클래스 외부에 공개되어 있다.    한가지 예외가 있는데
우리가 밑줄 두개로 시작하는 데이터 멤벌르 정의할때 , 즉 예를들어 __privatevar 와 같이 하면 , 파이썬이 이것을
클래스 외부로 드러나지 않도록 숨겨준다.
이건 클래스나 객체에 속해 있는 어떤 변수에나 적용된다.     클래스와 객체에 정의된 모든 이름은
밑줄로 시작하지 않는 이상 외부로 공개하고 다른 클래스나 객체에서 불러와 사용할 수 있도록 하는 규칙을

따르는것이 좋다.     

'Programming > Python' 카테고리의 다른 글

입력과 출력  (0) 2017.11.13
상속  (0) 2017.11.13
객체 지향 프로그래밍 ( Object - Oriented Programming )  (0) 2017.11.12
문자열 보충설명  (0) 2017.11.11
집합 그리고 참조  (0) 2017.11.11