복붙노트

[PYTHON] super ()가 "TypeError : 새 스타일 클래스의 경우 classobj가 아닌 유형이어야 함"을 발생시킵니다.

PYTHON

super ()가 "TypeError : 새 스타일 클래스의 경우 classobj가 아닌 유형이어야 함"을 발생시킵니다.

다음 super ()를 사용하면 TypeError가 발생합니다. 그 이유는 무엇입니까?

>>> from  HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
...     def __init__(self):
...         super(TextParser, self).__init__()
...         self.all_data = []
...         
>>> TextParser()
(...)
TypeError: must be type, not classobj

StackOverflow에도 비슷한 질문이 있습니다. Python super ()는 TypeError를 발생시킵니다. 여기서 오류는 사용자 클래스가 새로운 스타일의 클래스가 아니라는 사실로 설명됩니다. 그러나 위 클래스는 객체에서 상속받은 새로운 스타일 클래스입니다.

>>> isinstance(HTMLParser(), object)
True

내가 뭘 놓치고 있니? 여기서 super ()를 어떻게 사용할 수 있습니까?

super (TextParser, self) 대신 HTMLParser .__ init __ (self)를 사용하면됩니다 .____ init __ ()는 작동하지만 TypeError를 이해하고 싶습니다.

추신 : Joachim은 새로운 스타일의 클래스 인스턴스가 객체가되는 것과 같지 않다고 지적했습니다. 반대 의견을 여러 번 읽으므로 혼란 스럽습니다 (객체 인스턴스 테스트에 기반한 새로운 스타일의 클래스 인스턴스 테스트 예제 : https://stackoverflow.com/revisions/2655651/3).

해결법

  1. ==============================

    1.좋아, 그것은 보통 "super ()는 구식 클래스와 함께 사용할 수 없다")입니다.

    좋아, 그것은 보통 "super ()는 구식 클래스와 함께 사용할 수 없다")입니다.

    그러나 중요한 점은 "이것은 새로운 스타일의 인스턴스 (즉, 객체)입니까?"라는 올바른 테스트입니다. ~이다.

    >>> class OldStyle: pass
    >>> instance = OldStyle()
    >>> issubclass(instance.__class__, object)
    False
    

    그리고 아닙니다 (질문에서와 같이) :

    >>> isinstance(instance, object)
    True
    

    클래스의 경우 올바른 "this is a new-style class"테스트는 다음과 같습니다.

    >>> issubclass(OldStyle, object)  # OldStyle is not a new-style class
    False
    >>> issubclass(int, object)  # int is a new-style class
    True
    

    중요한 점은 예전 스타일의 클래스를 사용하면 인스턴스의 클래스와 그 유형이 구분된다는 점입니다. 여기서 OldStyle () .__ class__은 개체에서 상속받지 않는 OldStyle이며 type (OldStyle ())은 개체 유형을 상속하는 인스턴스 유형입니다. 기본적으로 이전 스타일의 클래스는 인스턴스 유형의 객체 만 작성합니다 (반면 새 스타일 클래스는 유형이 클래스 자체 인 객체를 만듭니다). 이는 아마도 OldStyle () 인스턴스가 객체 인 이유 일 것입니다. 객체의 type ()이 객체에서 상속받습니다. 객체에서 상속받지 않는 클래스는 이전 유형의 클래스가 인스턴스 유형의 새 객체를 생성하기 만합니다. 부분 참조 : https://stackoverflow.com/a/9699961/42973.

    추신 : 새로운 스타일의 클래스와 이전 스타일의 클래스의 차이점은 다음과 같이 볼 수 있습니다.

    >>> type(OldStyle)  # OldStyle creates objects but is not itself a type
    classobj
    >>> isinstance(OldStyle, type)
    False
    >>> type(int)  # A new-style class is a type
    type
    

    (구식 클래스는 유형이 아니므로 인스턴스의 유형이 될 수 없습니다.)

  2. ==============================

    2.super ()는 새로운 스타일 클래스에서만 사용할 수 있습니다. 즉, 루트 클래스가 'object'클래스에서 상속해야합니다.

    super ()는 새로운 스타일 클래스에서만 사용할 수 있습니다. 즉, 루트 클래스가 'object'클래스에서 상속해야합니다.

    예를 들어 최상위 클래스는 다음과 같아야합니다.

    class SomeClass(object):
        def __init__(self):
            ....
    

    아니

    class SomeClass():
        def __init__(self):
            ....
    

    그래서 해결책은 다음과 같이 부모의 init 메소드를 직접 호출하는 것입니다.

    class TextParser(HTMLParser):
        def __init__(self):
            HTMLParser.__init__(self)
            self.all_data = []
    
  3. ==============================

    3.TextParser 클래스 (HTMLParser, object) :를 사용할 수도 있습니다. 이것은 TextParser를 새로운 스타일의 클래스로 만들고 super ()를 사용할 수 있습니다.

    TextParser 클래스 (HTMLParser, object) :를 사용할 수도 있습니다. 이것은 TextParser를 새로운 스타일의 클래스로 만들고 super ()를 사용할 수 있습니다.

  4. ==============================

    4.문제는 슈퍼가 객체를 조상으로 필요로한다는 것입니다.

    문제는 슈퍼가 객체를 조상으로 필요로한다는 것입니다.

    >>> class oldstyle:
    ...     def __init__(self): self.os = True
    
    >>> class myclass(oldstyle):
    ...     def __init__(self): super(myclass, self).__init__()
    
    >>> myclass()
    TypeError: must be type, not classobj
    

    면밀히 검토하면 다음과 같은 결과가 나옵니다.

    >>> type(myclass)
    classobj
    

    그러나:

    >>> class newstyle(object): pass
    
    >>> type(newstyle)
    type    
    

    따라서 문제의 해결책은 HTMLParser뿐만 아니라 객체를 상속받는 것입니다. 그러나 객체가 클래스 MRO에서 마지막에 오는지 확인하십시오.

    >>> class myclass(oldstyle, object):
    ...     def __init__(self): super(myclass, self).__init__()
    
    >>> myclass().os
    True
    
  5. ==============================

    5.상속 트리 (버전 2.6에서)를 보면, HTMLParser는 SGMLParser에서 상속되며, 객체로부터 상속받지 않는 ParserBase를 상속받습니다. 나는. HTMLParser는 구식 클래스입니다.

    상속 트리 (버전 2.6에서)를 보면, HTMLParser는 SGMLParser에서 상속되며, 객체로부터 상속받지 않는 ParserBase를 상속받습니다. 나는. HTMLParser는 구식 클래스입니다.

    isinstance에 대한 검사에 관해서는 ipython에서 간단한 테스트를 수행했습니다.

    In [1]: class A:
       ...:     pass
       ...: 
    
    In [2]: isinstance(A, object)
    Out[2]: True
    

    클래스가 구식 클래스 인 경우에도 여전히 객체의 인스턴스입니다.

  6. ==============================

    6.올바른 방법은 '객체'를 상속받지 않는 구식 클래스에서 다음과 같이 수행됩니다.

    올바른 방법은 '객체'를 상속받지 않는 구식 클래스에서 다음과 같이 수행됩니다.

    class A:
        def foo(self):
            return "Hi there"
    
    class B(A):
        def foo(self, name):
            return A.foo(self) + name
    
  7. from https://stackoverflow.com/questions/9698614/super-raises-typeerror-must-be-type-not-classobj-for-new-style-class by cc-by-sa and MIT license