Computer >> 컴퓨터 >  >> 프로그램 작성 >> Python

Python에서 메타클래스를 사용한 메타 프로그래밍


메타프로그래밍이라는 용어는 컴퓨터 프로그램이 스스로를 조작하거나 알고 있는 컴퓨터 프로그래밍을 의미합니다. Python은 메타클래스라는 새로운 유형의 클래스를 통해 클래스에 대한 메타프로그래밍을 지원합니다.

파이썬에서 메타 클래스를 통한 메타 프로그래밍은 기존 코드를 수정, 래핑 또는 생성하여 코드를 조작하는 함수 및 클래스를 빌드하는 것입니다.

메타 프로그래밍의 주요 기능은 -

  • 메타클래스
  • 장식가
  • 클래스 데코레이터

메타클래스란 무엇입니까

메타클래스에 대한 매우 제한된 정의는 클래스를 생성하는 클래스일 수 있습니다. Python은 모든 것이 객체이고 클래스도 예외가 아닌 객체 지향 언어입니다. class 키워드로 클래스를 정의하면 파이썬은 실제로 그것을 실행한 다음 객체를 생성합니다. 객체이기 때문에 속성을 할당, 복사, 추가, 기능 매개변수 등으로 할 수 있습니다. 메타클래스를 사용하면 클래스의 속성 수정, 속성의 합법성 확인 등과 같은 클래스 생성을 제어할 수 있습니다.

파이썬 내장 메타클래스

모든 클래스의 메타 클래스는 유형입니다.

class a:
pass

print(type(a))

출력:

<class 'type'>

위의 출력에서 ​​"a"(class)가 클래스 유형의 객체임을 알 수 있습니다. "a"(class)는 클래스 유형의 인스턴스라고 말할 수도 있습니다. 따라서 유형은 메타 클래스입니다. 따라서 파이썬에서 모든 클래스는 내장 메타클래스 유형에 속합니다.

Python에서 메타클래스를 사용한 메타 프로그래밍

메타클래스를 사용하여 파이썬 클래스 만들기

위의 예에서 보았듯이 유형은 기본 메타클래스입니다. 이 기본 메타클래스(유형)를 사용하여 새 클래스를 만들 수 있습니다.

>>> class hello(object):
pass

이 방법으로도 수동으로 생성할 수 있습니다 -

>>> hello = type('hello', (), {})
>>> print(hello)# returns a class object

>>> print(hello()) # creates an instance with the class
<__main__.hello object at 0x05D86830>
의 .hello 개체

유형은 클래스의 속성을 정의하기 위해 사전을 허용하므로

>>> class hello(object):
   world = True

위의 코드는 다음과 유사합니다.

hello = type('hello', (), {'world' : True})

메타클래스 생성

그렇다면 메타클래스는 언제 생성해야 할까요? 클래스의 속성을 확인하거나 수정하는 등 클래스 생성을 제어하고 싶을 때.

클래스의 인스턴스화 프로세스 -

  • __new__()를 호출하여 인스턴스 생성
  • 위에서 생성된 인스턴스를 초기화하기 위해 __init__() 호출

따라서 사용자 정의 메타클래스를 만들 때 실제로 부모 클래스의 __new__() 또는 __init__ 메서드를 변경합니다.

Example1 - 클래스의 속성을 수정한 메타클래스

class LowercaseMeta(type):
   def __new__(mcs, name, bases, attrs):
      lower_attrs = {}
      for k, v in attrs.items():
         if not k.startswith('__'):
            lower_attrs[k.lower()] = v
         else:
            lower_attrs[k] = v
      return type.__new__(mcs, name, bases, lower_attrs)
class LowercaseClass(metaclass=LowercaseMeta):
   BAR = True
   def HELLO(self):
      print('hello')

print(dir(LowercaseClass))
LowercaseClass().hello()

출력

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'hello']
hello

Example2 - 클래스에 추가 속성 추가

class ListMeta(type):
   def __new__(mcs, name, bases, attrs):
      attrs['add'] = lambda self, value: self.append(value)
      return type.__new__(mcs, name, bases, attrs)
class MyList(list, metaclass=ListMeta):
pass
l = MyList()
l.add(1)
print(l)
def class_decorator(cls):
   cls.add = lambda self, value: self.append(value)
   return cls

@class_decorator
class MyList(list):
   pass
l = MyList()
l.append(1)
print(l)

출력

[1]
[1]

__metaclass__ 속성

파이썬에서 우리는 클래스를 가지고 있거나 그 베이스 중 하나에 __metaclass__ 속성이 있습니다. 이는 메타클래스로 간주되며 else 유형은 메타클래스입니다. 클래스를 −

로 작성할 때 __metaclass__ 속성을 가질 수 있습니다.

와 같은 클래스를 정의하면 어떻게 될까요?
class hello(object):
   x = 10

위의 Hello 클래스에는 __metaclass__ 속성이 없으므로 대신 type을 사용하고 클래스 생성은 −

hello = type(name, bases, dict)

Hello에 정의된 메타클래스가 있는 경우 -

class hello(object):
__metaclass__ = myMetaClass
pass

이제 위의 예에서 클래스 생성은 type 대신 myMetaClass를 사용하여 수행됩니다. 안녕하세요 =myMetaClass(이름, 베이스, 사전)