개발/Python

[파이썬] 클래스 개체에서 새 인스턴스를 만드는 방법

MinorMan 2022. 10. 9. 04:02
반응형

<질문>

Python에서 클래스의 인스턴스를 동적으로 생성해야 합니다. 기본적으로 load_module 및 inspect 모듈을 사용하여 클래스를 클래스 개체로 가져오고 로드하지만 이 클래스 개체의 인스턴스를 만드는 방법을 알 수 없습니다.


<답변1>

나는이 페이지로 나를 데려온 질문에 대한 답을 알아 냈습니다. 아무도 내 질문에 대한 답변을 실제로 제안하지 않았기 때문에 게시할 것이라고 생각했습니다.

class k:
  pass

a = k()
k2 = a.__class__
a2 = k2()

이 시점에서 및 a2는 모두 동일한 클래스(클래스 k)의 인스턴스입니다.


<답변2>

다음과 같이 세 개의 매개변수를 사용하여 내장된 "유형"을 호출하기만 하면 됩니다.

ClassName = type("ClassName", (Base1, Base2,...), classdictionary)

업데이트 아래 의견에 명시된 바와 같이 이것은 이 질문에 대한 답변이 전혀 아닙니다. 일부 사람들이 동적으로 클래스를 생성하려고 시도하는 힌트가 있기 때문에 삭제되지 않은 상태로 유지합니다. 이것이 바로 위의 라인이 하는 일입니다.

클래스의 객체를 생성하려면 허용된 답변에 있는 참조도 있으므로 클래스를 호출하기만 하면 됩니다.

instance = ClassObject()

따라서 인스턴스화 메커니즘은 다음과 같습니다.

파이썬은 사용하지 않습니다new 일부 언어에서 사용하는 키워드 - 대신 데이터 모델은 다른 호출 가능 항목과 동일한 구문으로 호출될 때 클래스의 인스턴스를 생성하는 데 사용되는 메커니즘을 설명합니다.

그 클래스'__call__ 메서드가 호출됩니다(클래스의 경우 해당 클래스는 일반적으로 내장된 "메타클래스"입니다.type). 이 호출의 일반적인 동작은 (의사) static을 호출하는 것입니다.__new__ 인스턴스화되는 클래스의 메소드__init__. 그만큼__new__ 메소드는 메모리 할당 등을 담당하며 일반적으로 다음과 같이 수행됩니다.__new__object 클래스 계층 루트입니다.

그래서 전화ClassObject() 불러일으키다ClassObject.__class__.call() (일반적으로type.__call__) 이것__call__ 메서드는 ClassObject 자체를 첫 번째 매개변수로 수신합니다. 순수 Python 구현은 다음과 같습니다.

class type:
    ...
    def __call__(cls, *args, **kw):
          constructor = getattr(cls, "__new__")
          instance = constructor(cls) if constructor is object.__new__ else constructor(cls, *args, **kw)
          instance.__init__(cls, *args, **kw)
          return instance

(문서에서 루트에 대한 추가 매개변수를 억제하는 정확한 정당화(또는 메커니즘)를 본 기억이 없습니다.__new__ 다른 클래스에 전달하지만 "실제 생활에서" 일어나는 일입니다.object.__new__ 추가 매개변수와 함께 호출되면 유형 오류가 발생합니다. 그러나__new__ 일반적으로 추가 매개 변수를 얻습니다)


<답변3>

다음은 동적으로 클래스를 생성하는 방법입니다.Child 귀하의 코드에서 가정Parent 이미 존재합니다... 명시적이지 않은 경우에도Parent 클래스, 당신은 사용할 수 있습니다object...

아래 코드는 다음을 정의합니다.__init__() 그런 다음 클래스와 연결합니다.

>>> child_name = "Child"
>>> child_parents = (Parent,)
>>> child body = """
def __init__(self, arg1):
    # Initialization for the Child class
    self.foo = do_something(arg1)
"""
>>> child_dict = {}
>>> exec(child_body, globals(), child_dict)
>>> childobj = type(child_name, child_parents, child_dict)
>>> childobj.__name__
'Child'
>>> childobj.__bases__
(,)
>>> # Instantiating the new Child object...
>>> childinst = childobj()
>>> childinst
<__main__.Child object at 0x1c91710>
>>>

<답변4>

가져오려는 클래스가 있는 모듈이 있는 경우 다음과 같이 할 수 있습니다.

module = __import__(filename)
instance = module.MyClass()

클래스 이름을 모르는 경우 모듈에서 사용 가능한 클래스를 반복할 수 있습니다.

import inspect
module = __import__(filename)
for c in module.__dict__.values():
    if inspect.isclass(c):
        # You may need do some additional checking to ensure 
        # it's the class you want
        instance = c()

<답변5>

클래스 개체가 있는 경우 괄호를 사용하여 호출하여 인스턴스화할 수 있습니다.

class MyClass: pass        
some_class = MyClass    
some_instance = some_class() # -> instance of MyClass
반응형