Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python에서 인스턴스 간에 공유되는 클래스 데이터 피하기

Python에서 클래스를 인스턴스화하면 해당 클래스에 정의된 모든 변수와 함수가 새로 생성된 인스턴스에 상속됩니다. 특히 클래스 레벨에서 선언된 가변(mutable) 객체는 모든 인스턴스가 하나의 객체를 함께 참조하게 되어, 의도치 않게 데이터가 공유되는 문제가 발생할 수 있습니다. 하지만 때로는 부모 클래스의 일부 변수를 인스턴스들이 공유하지 않기를 원하는 경우도 있습니다. 이 글에서는 이러한 문제를 해결하는 두 가지 방법을 코드 예제와 함께 살펴보겠습니다.

문제 상황: 인스턴스화 예제

아래 예제는 클래스 본문에 직접 선언된 변수가 여러 인스턴스 사이에서 어떻게 공유되는지 보여줍니다.

class MyClass:
    listA = []

# 두 개의 인스턴스 생성
x = MyClass()
y = MyClass()

# 각 인스턴스의 리스트 조작
x.listA.append(10)
y.listA.append(20)
x.listA.append(30)
y.listA.append(40)

# 결과 출력
print("Instance X: ", x.listA)
print("Instance Y: ", y.listA)

출력 결과

Instance X: [10, 20, 30, 40]
Instance Y: [10, 20, 30, 40]

x와 y는 서로 다른 인스턴스임에도 불구하고 동일한 결과가 출력되었습니다. 그 이유는 listA클래스 속성(class attribute)으로 선언되어 있고, 리스트는 가변 객체이기 때문입니다. 따라서 x.listA.append()y.listA.append()는 결국 같은 리스트 객체를 수정하게 됩니다.

방법 1: __init__ 메서드로 인스턴스 변수 선언하기

가장 권장되는 방법은 __init__(생성자) 메서드 안에서 self를 사용해 변수를 선언하는 것입니다. 이렇게 하면 변수가 인스턴스 속성(instance attribute)이 되어, 각 인스턴스마다 독립적인 객체가 생성되므로 인스턴스 간에 공유되지 않습니다.

예제

class MyClass:
    def __init__(self):
        self.listA = []

# 두 개의 인스턴스 생성
x = MyClass()
y = MyClass()

# 각 인스턴스의 리스트 조작
x.listA.append(10)
y.listA.append(20)
x.listA.append(30)
y.listA.append(40)

# 결과 출력
print("Instance X: ", x.listA)
print("Instance Y: ", y.listA)

출력 결과

Instance X: [10, 30]
Instance Y: [20, 40]

이제 각 인스턴스는 자신만의 독립적인 리스트를 가지며, 한 인스턴스에서 수행한 변경 사항이 다른 인스턴스에는 영향을 주지 않습니다.

방법 2: 클래스 외부에서 변수 재선언하기

또 다른 방법은 인스턴스를 생성한 후, 각 인스턴스에 대해 해당 변수를 새로 할당(재선언)하는 것입니다. 변수가 다시 초기화되면 기존 클래스 속성과의 연결이 끊어지고 인스턴스 고유의 속성이 되므로, 더 이상 인스턴스 간에 공유되지 않습니다.

예제

class MyClass:
    listA = []

# 두 개의 인스턴스 생성
x = MyClass()
y = MyClass()

# 각 인스턴스에서 변수를 새로 할당하여 독립시킴
x.listA = []
y.listA = []

# 각 인스턴스의 리스트 조작
x.listA.append(10)
y.listA.append(20)
x.listA.append(30)
y.listA.append(40)

# 결과 출력
print("Instance X: ", x.listA)
print("Instance Y: ", y.listA)

출력 결과

Instance X: [10, 30]
Instance Y: [20, 40]

정리

Python에서 클래스 본문에 가변 객체(리스트, 딕셔너리 등)를 직접 선언하면 모든 인스턴스가 이를 공유하게 됩니다. 이를 피하려면 다음 두 가지 방법을 사용할 수 있습니다.

  • __init__ 메서드 활용: 생성자 안에서 self.변수명 형태로 선언하여 인스턴스마다 독립적인 속성을 생성합니다. 가장 깔끔하고 권장되는 방식입니다.
  • 외부에서 변수 재선언: 인스턴스 생성 후 각 인스턴스에 변수를 새로 할당하여 클래스 속성과의 공유 관계를 끊습니다.

일반적으로는 첫 번째 방법인 __init__ 메서드를 활용하는 것이 코드의 의도를 명확히 드러내고 유지보수 측면에서도 유리합니다.