sourcecode

클래스가 하위 분류될 때 코드를 실행하는 방법은 무엇입니까?

copyscript 2023. 7. 18. 21:53
반응형

클래스가 하위 분류될 때 코드를 실행하는 방법은 무엇입니까?

제 수업이 하위 분류될 때 코드를 트리거할 수 있는 방법이 있습니까?

class SuperClass:
    def triggered_routine(subclass):
        print("was subclassed by " + subclass.__name__)

magically_register_triggered_routine()

print("foo")

class SubClass0(SuperClass):
    pass

print("bar")

class SubClass1(SuperClass):
    print("test")

출력해야 합니다.

foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1

클래스(기본값)는 다음의 인스턴스입니다.type수업의 예로.Foo에 의해 생성됨foo = Foo(...)의 예.type(즉, 클래스)는 다음에 의해 생성됩니다.myclass = type(name, bases, clsdict).

만약 여러분이 클래스를 만드는 순간에 특별한 일이 일어나기를 원한다면, 여러분은 클래스를 만드는 것을 수정해야 합니다. type이를 위한 방법은 다음의 하위 클래스를 정의하는 것입니다.type메타 클래스

메타 클래스는 클래스에 대한 것이고 클래스는 인스턴스에 대한 것입니다.

Python2에서 당신은 클래스의 메타클래스를 정의할 것입니다.

class SuperClass:
    __metaclass__ = Watcher

어디에Watcher의 하위 클래스입니다.type.

Python3에서 구문이 다음으로 변경되었습니다.

class SuperClass(metaclass=Watcher)

둘 다 같은 값입니다.

Superclass = Watcher(name, bases, clsdict)

이 경우에는name문자열과 같습니다.'Superclass',그리고.bases튜플입니다.(object, ).그clsdict클래스 정의 본문에 정의된 클래스 속성 사전입니다.

와의 유사성에 유의하십시오.myclass = type(name, bases, clsdict).

그래서, 당신이 수업의 것을 사용하는 것처럼.__init__인스턴스 생성 순간의 이벤트를 제어하기 위해 메타클래스를 사용하여 클래스 생성 순간의 이벤트를 제어할 수 있습니다.__init__:


class Watcher(type):
    def __init__(cls, name, bases, clsdict):
        if len(cls.mro()) > 2:
            print("was subclassed by " + name)
        super(Watcher, cls).__init__(name, bases, clsdict)

class SuperClass:
    __metaclass__ = Watcher


print("foo")

class SubClass0(SuperClass):
  pass

print("bar")

class SubClass1(SuperClass):
  print("test")

인쇄물

foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1

편집: 제 이전 게시물은 실제로 작동하지 않았습니다.하위 분류 위치classmethod예상대로 작동하지 않습니다.

먼저, 우리는 메타 클래스에 이 특정 메서드가 하위 클래스 동작에 대해 특별하게 호출되어야 한다는 것을 알리는 방법을 가지고 싶습니다. 우리는 단지 호출하고 싶은 함수에 속성을 설정할 것입니다.편의를 위해, 우리는 그 기능을 심지어 하나로 바꿀 것입니다.classmethod그래서 그것이 발견된 진짜 기본 클래스도 발견될 수 있습니다.가장 편리한 데코레이터로 사용할 수 있도록 클래스 메소드를 반납하겠습니다.

import types
import inspect

def subclass_hook(func):
    func.is_subclass_hook = True
    return classmethod(func)

우리는 또한 편리한 방법을 원할 것입니다.subclass_hook데코레이터가 사용되었습니다.우리는 알고 있습니다.classmethod사용되었으니 확인하고 그 다음에 찾아보겠습니다.is_subclass_hook기여하다.

def test_subclass_hook(thing):
    x = (isinstance(thing, types.MethodType) and
         getattr(thing.im_func, 'is_subclass_hook', False))
    return x

마지막으로, 정보에 따라 작동하는 메타 클래스가 필요합니다.대부분의 경우 여기서 가장 흥미로운 작업은 제공된 각 베이스에서 후크를 확인하는 것입니다.그런 식으로, 슈퍼는 가장 놀라운 방식으로 작동합니다.

class MyMetaclass(type):
    def __init__(cls, name, bases, attrs):
        super(MyMetaclass, cls).__init__(name, bases, attrs)

        for base in bases:
            if base is object:
                continue
            for name, hook in inspect.getmembers(base, test_subclass_hook):
                hook(cls)

그리고 그것으로 충분합니다.

>>> class SuperClass:
...     __metaclass__ = MyMetaclass
...     @subclass_hook
...     def triggered_routine(cls, subclass):
...         print(cls.__name__ + " was subclassed by " + subclass.__name__)

>>> class SubClass0(SuperClass):
...     pass
SuperClass was subclassed by SubClass0

>>> class SubClass1(SuperClass):
...     print("test")
test
SuperClass was subclassed by SubClass1

언급URL : https://stackoverflow.com/questions/18126552/how-to-run-code-when-a-class-is-subclassed

반응형