[python] 파이썬에서 이전 스타일과 새로운 스타일 클래스의 차이점은 무엇입니까?

파이썬에서 이전 스타일과 새로운 스타일 클래스의 차이점은 무엇입니까? 언제 하나를 사용해야합니까?



답변

에서 새로운 스타일과 클래식 클래스 :

Python 2.1까지, 구식 클래스는 사용자가 사용할 수있는 유일한 특징이었습니다.

(구식) 클래스의 개념은 유형의 개념과 관련이 없습니다 x. 구식 클래스의 인스턴스 인 경우 클래스를 x.__class__
지정 x하지만 type(x)항상 <type
'instance'>
입니다.

이는 클래스와 관계없이 모든 이전 스타일 인스턴스가 인스턴스라는 단일 내장 유형으로 구현된다는 사실을 반영합니다.

새로운 스타일의 클래스가 Python 2.2에 도입되어 class와 type의 개념을 통합했습니다 . 새로운 스타일의 클래스는 단순히 사용자 정의 유형입니다.

x가 새 스타일 클래스의 인스턴스 인 경우 type(x)일반적으로 다음과 동일합니다 x.__class__(이는 보장되지 않지만 새 스타일 클래스 인스턴스는에 대해 반환 된 값을 재정의 할 수 있음 x.__class__).

새로운 스타일의 클래스를 도입하는 주요 동기는 완전한 메타 모델을 가진 통합 객체 모델을 제공하는 것 입니다.

또한 대부분의 내장 유형을 서브 클래 싱하는 기능이나 계산 된 속성을 가능하게하는 “설명자”의 도입과 같은 많은 즉각적인 이점이 있습니다.

호환성 때문에 클래스는 기본적으로 여전히 구식 입니다.

새 스타일 클래스는 다른 새 스타일 클래스 (예 : 유형)를 부모 클래스로 지정하거나 다른 부모가 필요하지 않은 경우 “최상위 유형”개체로 지정하여 만듭니다.

새 스타일 클래스의 동작은 반환되는 유형 외에 여러 가지 중요한 세부 사항에서 이전 스타일 클래스의 동작과 다릅니다.

이러한 변경 중 일부는 특수 메소드가 호출되는 방식과 같이 새 객체 모델의 기본입니다. 다른 것들은 다중 상속의 경우 메소드 해결 순서와 같이 호환성 문제로 이전에 구현할 수 없었던 “수정”입니다.

파이썬 3에는 새로운 스타일의 클래스 만 있습니다 .

서브 클래스의 유무에 관계없이 object클래스는 파이썬 3에서 새로운 스타일입니다.


답변

선언 현명한 :

새 스타일 클래스는 object 또는 다른 새 스타일 클래스에서 상속됩니다 .

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

구식 수업은 그렇지 않습니다.

class OldStyleClass():
    pass

파이썬 3 참고 :

Python 3은 이전 스타일 클래스를 지원하지 않으므로 위에서 언급 한 형식 중 하나가 새로운 스타일 클래스가됩니다.


답변

이전 스타일 클래스와 새로운 스타일 클래스 사이의 중요한 동작 변경

  • 감독자 추가
  • MRO 변경 (아래에 설명)
  • 서술자 추가
  • 새로운 스타일 클래스 객체는 Exception(아래 예) 에서 파생되지 않으면 올릴 수 없습니다
  • __slots__ 추가

MRO (Method Resolution Order)가 변경되었습니다.

다른 답변에서 언급되었지만 고전 MRO와 C3 MRO (새로운 스타일 클래스에서 사용)의 차이점에 대한 구체적인 예가 있습니다.

문제는 속성 (메소드 및 멤버 변수 포함)이 다중 상속에서 검색되는 순서입니다.

클래식 수업 은 왼쪽에서 오른쪽으로 깊이 우선 검색을 수행합니다. 첫 경기에서 멈춰라. __mro__속성 이 없습니다 .

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

새로운 스타일의 수업 MRO는 단일 영어 문장으로 합성하기가 더 복잡합니다. 여기 에 자세히 설명되어 있습니다 . 그 속성 중 하나는 기본 클래스가 모든 파생 클래스가 검색된 후에 만 ​​검색된다는 것입니다. __mro__검색 순서를 표시 하는 속성이 있습니다.

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

새로운 스타일 클래스 객체는 Exception

파이썬 2.5 주변에서 많은 클래스가 생길 수 있었고 파이썬 2.6 주변에서는이 클래스가 제거되었습니다. 파이썬 2.7.3에서 :

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False


답변

이전 스타일 클래스는 여전히 속성 조회 속도가 약간 빠릅니다. 이것은 일반적으로 중요하지 않지만 성능에 민감한 Python 2.x 코드에서 유용 할 수 있습니다.

[3]에서 : 클래스 A :
   ... : 데프 __init __ (자체) :
   ... : self.a = '안녕하세요'
   ... :

[4]에서 : 클래스 B (객체) :
   ... : 데프 __init __ (자체) :
   ... : self.a = '안녕하세요'
   ... :

[6]에서 : aobj = A ()
[7]에서 : bobj = B ()

[8]에서 : % timeit aobj.a
10000000 루프, 루프 당 3 : 78.7ns

[10]에서 : % timeit bobj.a
10000000 루프, 루프 당 3 : 86.9ns


답변

귀도는 파이썬의 새로운 스타일과 구식 클래스에 대한 훌륭한 기사 인 New-Style Classes에 대한 The Inside Story를 작성 했습니다.

파이썬 3에는 새로운 스타일의 클래스 만 있습니다. ‘구식 클래스’를 작성하더라도 묵시적으로 파생됩니다 object.

새로운 스타일 클래스에는 super새로운 C3 mro , 일부 마법적인 방법 등과 같은 구식 클래스에서 부족한 몇 가지 고급 기능이 있습니다 .


답변

여기에는 매우 실용적이고 참 / 거짓의 차이가 있습니다. 다음 코드의 두 버전 간의 유일한 차이점은 두 번째 버전에서 Personobject 로부터 상속 한다는 것입니다 . 그 외에 두 버전은 동일하지만 결과가 다릅니다.

  1. 구식 수업

    class Person():
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed1 is ahmed2
    print ahmed1
    print ahmed2
    
    
    >>> False
    <__main__.Person instance at 0xb74acf8c>
    <__main__.Person instance at 0xb74ac6cc>
    >>>
    
  2. 새로운 스타일의 수업

    class Person(object):
        _names_cache = {}
        def __init__(self,name):
            self.name = name
        def __new__(cls,name):
            return cls._names_cache.setdefault(name,object.__new__(cls,name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print ahmed2 is ahmed1
    print ahmed1
    print ahmed2
    
    >>> True
    <__main__.Person object at 0xb74ac66c>
    <__main__.Person object at 0xb74ac66c>
    >>>

답변

새로운 스타일의 클래스 object는 파이썬 2.2부터 (예를 들어 class Classname(object):대신 class Classname:) 상속 받아야합니다 . 핵심 변경 사항은 형식과 클래스를 통합하는 것이며, 이로 인한 부작용은 기본 제공 형식에서 상속 할 수 있다는 것입니다.

자세한 내용은 descrintro 를 읽으십시오 .