64 lines
4.0 KiB
Markdown
64 lines
4.0 KiB
Markdown
# 메타클래스
|
|
메타클래스는 파이썬에서 클래스를 생성하는 데 사용되는 클래스입니다. 즉, 클래스의 클래스라고 할 수 있습니다. 일반적인 클래스가 객체를 생성하는 틀이라면, 메타클래스는 그러한 클래스 자체를 생성하는 틀이라고 생각하면 됩니다.
|
|
|
|
* 클래스 생성 과정 제어: 클래스가 생성되는 시점에 특정 작업을 수행하거나, 클래스의 속성을 동적으로 변경할 수 있습니다.
|
|
* 클래스 레벨의 로깅: 클래스 생성 시 로그를 남기거나, 프로파일링 정보를 수집할 수 있습니다.
|
|
* 싱글톤 패턴 구현: 특정 클래스의 인스턴스가 단 하나만 존재하도록 제한할 수 있습니다.
|
|
* 데코레이터를 클래스 레벨로 확장: 클래스 전체에 적용되는 데코레이터를 만들 수 있습니다.
|
|
|
|
```python
|
|
class Meta(type):
|
|
def __new__(cls, name, bases, namespace, **kwargs):
|
|
print(f"Creating class: {name}")
|
|
return super().__new__(cls, name, bases, namespace, **kwargs)
|
|
|
|
class MyClass(metaclass=Meta):
|
|
pass
|
|
|
|
# MyClass 생성 시 Meta.__new__ 메서드가 호출됨
|
|
```
|
|
위 예시에서 Meta는 메타클래스이고, MyClass는 Meta 메타클래스를 사용하여 생성된 클래스입니다. `__new__` 메서드는 새로운 클래스가 생성될 때 호출되며, 클래스 생성 과정에 개입하여 추가적인 작업을 수행할 수 있습니다.
|
|
|
|
### 메타클래스의 주요 메서드
|
|
|
|
* `__new__`: 새로운 인스턴스를 생성합니다. 클래스를 생성할 때 호출됩니다.
|
|
* `__init__`: 생성된 인스턴스를 초기화합니다. 클래스가 생성된 후 호출됩니다.
|
|
* `__call__`: 클래스를 함수처럼 호출할 때 실행됩니다.
|
|
|
|
## 싱글턴 패턴의 구현
|
|
싱글턴 패턴은 하나의 클래스에 대해 오직 하나의 인스턴스만 생성하고, 이 인스턴스에 대한 전역적인 접근점을 제공하는 디자인 패턴입니다. 즉, 싱글톤 클래스는 프로그램 전체에서 단 한 번만 생성되고, 그 인스턴스를 여러 곳에서 공유하여 사용할 수 있습니다.
|
|
|
|
* 전역 상태 관리: 프로그램 전체에서 공유해야 하는 상태를 관리하는 데 유용합니다. 예를 들어, 로그 파일, 설정 정보 등을 관리하는 클래스를 싱글톤으로 만들 수 있습니다.
|
|
* 자원 공유: 단 하나의 인스턴스만 사용하기 때문에 자원 낭비를 줄이고, 자원 공유를 효율적으로 할 수 있습니다.
|
|
* 모듈 간 통신: 서로 다른 모듈 간에 데이터를 주고받을 때, 싱글톤을 통해 중앙 집중식으로 관리할 수 있습니다.
|
|
|
|
```python
|
|
class Singleton:
|
|
__instance = None
|
|
|
|
def __new__(cls):
|
|
if cls.__instance is None:
|
|
cls.__instance = super().__new__(cls)
|
|
return cls.__instance
|
|
```
|
|
* `__new__` 메서드: 클래스의 인스턴스를 생성하는 메서드입니다.
|
|
* `__instance` 클래스 변수: 생성된 인스턴스를 저장합니다.
|
|
* 처음 인스턴스를 생성할 때 `__instance`에 저장하고, 이후에는 이미 생성된 인스턴스를 반환합니다.
|
|
|
|
## 상속 제한
|
|
파이썬에서 클래스를 상속 불가능하게 만드는 가장 일반적인 방법은 metaclass를 사용하는 것입니다. metaclass는 클래스를 생성하는 클래스로, 클래스 생성 과정에 개입하여 다양한 기능을 구현할 수 있습니다.
|
|
|
|
```python
|
|
class NonInheritableMeta(type):
|
|
def __new__(cls, name, bases, namespace, **kwargs):
|
|
if bases:
|
|
raise TypeError("이 클래스는 상속될 수 없습니다.")
|
|
return super().__new__(cls, name, bases, namespace, **kwargs)
|
|
|
|
class BaseClass(metaclass=NonInheritableMeta):
|
|
pass
|
|
|
|
class DerivedClass(BaseClass): # TypeError 발생
|
|
pass
|
|
```
|
|
위 코드에서 `NonInheritableMeta`는 상속을 불가능하게 만드는 metaclass입니다. `__new__` 메서드에서 `bases`가 비어있지 않으면 (즉, 상속을 시도하면) `TypeError`를 발생시켜 상속을 막습니다. |