파이썬에서 변수가 객체를 바인딩할때, 이러한 매핑 관계를 저장하는 공간을 네임스페이스라고 한다.
class Shirt:
color = "blue"
print(Shirt.color)
s1 = Shirt()
s2 = Shirt()
print(s1.color)
s1.color = 'red'
print(s1.color)
print(s2.color)
Shirt라는 클래스를 만들고 color이라는 변수를 선언했다.
그리고 인스턴스로 s1, s2를 각각 만들었다.
인스턴스를 만들면 기존 클래스 네임스페이스와는 별도의 네임스페이스를 가진다.
그리고 s1.color을 선언해주었다.
그리고 s2.color을 호출했는데, s2 인스턴스는 따로 변수를 선언하지 않았기때문에 네임스페이스에 매핑된 정보가 없다.
그래서 클래스 네임스페이스로 올라가서 Shirt.color 값을 출력한다.
즉, 인스턴스의 네임스페이스에 정보가 없을땐 클래스 네임스페이스로 올라간다.
당연해보이지만 중요한 개념이다.
위에서 네임스페이스에 대해 배웠다면 클래스 변수와 인스턴스 변수의 차이에 대해 이해할 수 있다.
클래스 변수는 범위가 클래스 전체에 적용되는 변수고, 인스턴스 변수는 범위가 인스턴스 하나에서만 적용되는 변수다.
기본적으로 모든 인스턴스는 클래스 변수를 공유하나, 인스턴스도 자신만의 변수를 가질 수 있다.
이해를 위해 아래의 예시를 보자
class Movie:
play = [1,2,3]
m1 = Movie()
m1.play+=[5]
print(Movie.play) # [1,2,3,5]
print(m1.play) # [1,2,3,5]
Movie 클래스의 play 변수는 [1,2,3]이고 해당 인스턴스는 생성하면 변수에 5를 추가한다.
그리고 m1 인스턴스를 생성한뒤 클래스, 인스턴스의 변수가 어떻게 변화하는지 보자
인스턴스의 변수를 조작했기 때문에 클래스 변수는 그대로라고 생각할 수 있지만, 실제로 값을 보면 Movie.play, m1.play 모두 값이 변화했다.
비슷하지만 다른 예시를 보자
class Movie:
play = [1,2,3]
m1 = Movie()
m1.play=[1,2,3]
m1.play+=[5]
print(Movie.play) # [1,2,3]
print(m1.play) # [1,2,3,5]
위의 예시와 비슷하지만 여기서는 결과가 다르게 나왔다.
이 차이가 바로 클래스 변수와 인스턴스 변수에서 발생한다.
첫번째 예시는 인스턴스를 생성했으나 따로 변수를 선언하지 않았다.
이럴 경우 인스턴스.변수명 으로 접근했을때 클래스.변수명 을 참조한다.
위에서 인스턴스의 네임스페이스가 없다면 클래스 네임스페이스를 가져온다는 것이 핵심이라고 한 이유가 바로 이것이다.
즉, 인스턴스.변수명 으로 접근해서 수정했지만, 해당 변수가 클래스 변수를 참조하고 있어서 클래스 변수가 수정되는 것이다.
두번째 예시를 보면 m1.play=[1,2,3] 이라고 인스턴스 변수로 선언을 하고 이를 수정했기 때문에 인스턴스 변수만 바뀌고 클래스 변수는 그대로인 것이다.
어떻게 보면 얕은 복사, 깊은 복사에서 공부한 내용과 비슷한 개념이다.
얕은 복사, 깊은 복사에서는 해당 객체가 mutable, immutable인지에 따라 결과가 달라졌는데 여기서도 마찬가지이다.
# immutable
class Movie:
play = 1
m1 = Movie()
m1.play+=5
print(Movie.play) # 1
print(m1.play) # 6
print(id(Movie.play), id(m1.play)) # 다름
# mutable
class Movie:
play = [1,2,3]
m1 = Movie()
m1.play+=[5]
print(Movie.play) # [1,2,3,5]
print(m1.play) # [1,2,3,5]
print(id(Movie.play),id(m1.play)) # 같음
클래스 변수를 mutable인 int와 immutable인 list로 각각 두고 그 결과를 살펴보았다.
int일땐 변수에 변화를 주면 클래스 변수와 인스턴스의 변수의 값이 달라지며 주소값 역시 달라지는데,
list에선 변수에 덧셈을 해도 클래스 변수와 인스턴스 변수가 같았으며 주소값 역시 같았다.
즉, mutable인 변수는 선언을 하기 전까진 클래스 변수를 참조한다는 것이다.
즉,