Python에서 이전 스타일 클래스와 새 스타일 클래스의 차이점은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/54867

문제

Python에서 이전 스타일 클래스와 새 스타일 클래스의 차이점은 무엇입니까?언제 둘 중 하나를 사용해야 합니까?

도움이 되었습니까?

해결책

에서 http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes :

Python 2.1까지는 사용자가 사용할 수 있는 유일한 버전이 이전 스타일 클래스였습니다.

(이전 스타일) 클래스 개념은 유형 개념과 관련이 없습니다.만약에 x 는 이전 스타일 클래스의 인스턴스입니다. x.__class__클래스를 지정합니다. x, 하지만 type(x) 항상 <type 'instance'>.

이는 클래스와 무관하게 모든 구식 인스턴스가 인스턴스라고하는 단일 내장 유형으로 구현된다는 사실을 반영합니다.

클래스와 유형의 개념을 통합하기 위해 Python 2.2에 새로운 스타일의 클래스가 도입되었습니다..새로운 스타일 클래스는 단순히 사용자 정의 유형일 뿐 그 이상도 그 이하도 아닙니다.

x가 새로운 스타일 클래스의 인스턴스인 경우 type(x) 일반적으로 동일합니다 x.__class__ (이것은 보장되지는 않지만-새 스타일의 클래스 인스턴스는 반환 된 값을 무시할 수 있습니다. x.__class__).

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

또한 대부분의 내장 유형을 서브 클래스하는 기능 또는 계산 된 속성을 가능하게하는 "디스크립터"의 도입과 같은 여러 가지 즉각적인 이점이 있습니다.

호환성상의 이유로 클래스는 기본적으로 여전히 구식입니다..

새로운 스타일 클래스는 다른 새 스타일 클래스를 지정하여 만들어집니다 (예 :유형) 부모 클래스 또는 다른 부모가 필요하지 않은 경우 "최상위 유형"오브젝트.

새로운 스타일 클래스의 행동은 유형의 반환과 함께 여러 가지 중요한 세부 사항에서 구식 클래스의 행동과 다릅니다.

이러한 변경 중 일부는 특별한 방법이 호출되는 방식과 같이 새로운 객체 모델의 기본입니다.다른 사람은 다중 상속의 경우 메소드 해상도 순서와 같이 호환성 문제에 대해 이전에 구현할 수없는 "수정"입니다.

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

하위클래스로 분류하더라도 상관없습니다. object 또는 수업은 Python 3에서 새 스타일입니다.

다른 팁

선언 방식:

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

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

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

class OldStyleClass():
    pass

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

  • 감독자 추가됨
  • MRO가 변경되었습니다(아래 설명 참조).
  • 설명자 추가됨
  • 새로운 스타일 클래스 객체는 다음에서 파생되지 않는 한 생성될 수 없습니다. Exception (아래 예)
  • __slots__ 추가됨

MRO(메소드 해결 순서)가 변경되었습니다.

다른 답변에서 언급되었지만 여기에는 클래식 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

Python 2.5 부근에서는 많은 클래스가 생성될 수 있었지만 Python 2.6 부근에서는 이것이 제거되었습니다.Python 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 코드에 유용할 수 있습니다.

In [3]: class A:
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

In [4]: class B(object):
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

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

In [8]: %timeit aobj.a
10000000 loops, best of 3: 78.7 ns per loop

In [10]: %timeit bobj.a
10000000 loops, best of 3: 86.9 ns per loop

귀도가 썼다 새로운 스타일의 수업에 대한 인사이드 스토리, Python의 새로운 스타일과 이전 스타일 클래스에 대한 정말 훌륭한 기사입니다.

Python 3에는 새 스타일 클래스만 있습니다. '이전 스타일 클래스'를 작성하더라도 암시적으로 다음에서 파생됩니다. object.

새로운 스타일의 클래스에는 이전 스타일의 클래스에는 없는 몇 가지 고급 기능이 있습니다. super 그리고 새로운 C3 mro, 일부 마법의 방법 등

다음은 매우 실용적인 True/False 차이입니다.다음 코드의 두 버전 간의 유일한 차이점은 두 번째 버전에서는 Person이 객체에서 상속된다는 것입니다.그 외에는 두 버전이 동일하지만 결과가 다릅니다.

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 Python 2.2 이상에서는 다음과 같이 작성해야 합니다(예: class Classname(object): 대신에 class Classname:).핵심 변경 사항은 유형과 클래스를 통합하는 것입니다. 이에 따른 좋은 부작용은 내장 유형에서 상속할 수 있다는 것입니다.

읽다 설명 상세 사항은.

새로운 스타일의 수업은 다음을 사용할 수 있습니다 super(Foo, self) 어디 Foo 수업이고 self 인스턴스입니다.

super(type[, object-or-type])

메소드 호출을 유형의 상위 또는 형제 클래스에 위임하는 프록시 객체를 반환합니다.이는 클래스에서 재정의된 상속된 메서드에 액세스하는 데 유용합니다.검색 순서는 유형 자체를 건너뛴다는 점을 제외하면 getattr()에서 사용하는 것과 동일합니다.

Python 3.x에서는 간단히 다음을 사용할 수 있습니다. super() 매개변수가 없는 클래스 내부.

아니면 항상 새로운 스타일의 클래스를 사용해야 합니다. ~하지 않는 한 2.2 이전 버전의 Python에서 작동해야 하는 코드가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top