Post

Python Shadowing

Python Shadowing

객체지향이 필요한 이유는 데이터(상태)행동(기능)을 하나로 묶어, 코드의 재사용성과 유지보수성을 높이기 위해서입니다. 이 과정에서 다음 개념들이 등장합니다:

클래스 변수 / 인스턴스 변수 — 모든 객체가 공유하는 값과, 각 객체가 개별로 가지는 값을 구분합니다. 인스턴스 메서드 / 클래스 메서드 / 정적 메서드 — 객체의 상태를 다루는 메서드, 클래스 자체의 속성을 다루는 메서드, 그리고 클래스와 무관하게 동작하는 함수를 나눕니다.

어떤 이름이 어디에 저장되는가(네임스페이스), 그리고 어떤 순서로 탐색되는지가 중요합니다.


1. 네임스페이스와 속성 탐색 순서

탐색 단계설명
obj.__dict__객체(인스턴스) 자체에 저장된 속성
obj.__class__.__dict__클래스에 정의된 속성
③ 부모 클래스들상속 계층을 MRO(Method Resolution Order)대로 검색

Shadowing = 하위 네임스페이스(①)가 같은 이름을 가지면 상위 속성을 “가림”.


2. 클래스 변수 vs 인스턴스 변수

1
2
3
4
5
class MyClass:
    class_var = 10          # 클래스 변수

    def __init__(self):
        self.inst_var = 20  # 인스턴스 변수
코드저장 위치결과
MyClass.class_varMyClass.__dict__['class_var']10
obj = MyClass()  
obj.inst_varobj.__dict__['inst_var']20
obj.class_var① 없음→② 클래스에서 탐색10
obj.class_var = 99obj.__dict__['class_var']=99 생성Shadowing 발생
1
2
3
4
print(obj.__dict__)      # {'inst_var': 20, 'class_var': 99}
print(MyClass.__dict__['class_var'])  # 10 (여전히 존재)
del obj.class_var
print(obj.class_var)     # 10 (Shadowing 해제 → 클래스 값 다시 보임)

3. 메서드 바인딩

종류선언 형태첫 인자바인딩 대상대표 쓰임
인스턴스 메서드def foo(self)self인스턴스객체 상태 이용·변경
클래스 메서드@classmethod
def foo(cls)
cls클래스공용 설정, 팩토리
정적 메서드@staticmethod
def foo()
(없음)없음유틸리티 함수

메서드도 Shadowing

1
2
3
4
5
6
7
8
9
10
11
12
class Greeting:
    @staticmethod
    def hi():
        print("Hi (static)")

g = Greeting()
g.hi()          # Hi (static)

g.hi = lambda: print("Hi (instance)")
g.hi()          # Hi (instance)  ← 인스턴스 속성이 클래스 속성을 가림
del g.hi
g.hi()          # Hi (static)    ← 복원

4. dir() vs __dict__ 빠른 점검

1
2
3
4
5
6
7
8
class Dog:
    species = ""
    def __init__(self, name): self.name = name

d = Dog("초코")
print(dir(d)[:5], "...")  # 수십 개 이름(내장·상속 포함) 리스트
print(d.__dict__)         # {'name': '초코'}
print(Dog.__dict__['species'])  # '개'
  • dir(obj)접근 가능한 모든 이름(문자열 리스트)
  • obj.__dict__객체가 직접 소유한 속성(딕셔너리)

맺음말

정리하면

  1. 저장 위치(인스턴스 vs 클래스)와 탐색 순서에 따라 shadowing이 일어납니다.
  2. 메서드 세 종류는 *“어떤 대상(self/cls/없음)에 자동으로 연결되어 동작하는지”*
    그리고 어떤 데이터 값을 다루는지에 따라 구분됩니다.
  3. dir()·__dict__로 네임스페이스를 바로 확인할 수 있습니다.

필요할 때마다 객체의 __dict__를 들여다보며 *“내가 지금 어디에 무엇을 만들고 있나?”*를 점검해 보세요. Shadowing을 활용하는데 도움이 되었기를 바랍니다.

This post is licensed under CC BY 4.0 by the author.