답변:
에서 새로운 스타일과 클래식 클래스 :
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에서 새로운 스타일입니다.
super()
구식 수업에서는 작동하지 않는 것과 같은 특정 기능이 있습니다. 이 기사에서 언급했듯이 MRO와 같은 기본적인 수정 사항과 특수한 방법이 있습니다.이를 사용하는 것이 좋습니다.
선언 현명한 :
새 스타일 클래스는 object 또는 다른 새 스타일 클래스에서 상속됩니다 .
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
구식 수업은 그렇지 않습니다.
class OldStyleClass():
pass
파이썬 3 참고 :
Python 3은 이전 스타일 클래스를 지원하지 않으므로 위에서 언급 한 형식 중 하나가 새로운 스타일 클래스가됩니다.
object
.
class AnotherOldStyleClass: pass
class A: pass
하고 class A(): pass
엄격하게 동일합니다. 첫 번째는 "A는 부모 클래스를 상속받지 않음" 을 의미하고 두 번째는 "A는 부모 클래스를 상속받지 않음"을 의미 합니다. 즉 아주 비슷 not is
하고is not
이전 스타일 클래스와 새로운 스타일 클래스 사이의 중요한 동작 변경
다른 답변에서 언급되었지만 고전 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
%timeit aobj.a
10000000 loops, best of 3: 66.1 ns per loop
%timeit bobj.a
10000000 loops, best of 3: 53.9 ns per loop
귀도는 파이썬의 새로운 스타일과 구식 클래스에 대한 훌륭한 기사 인 New-Style Classes에 대한 The Inside Story를 작성 했습니다.
파이썬 3에는 새로운 스타일의 클래스 만 있습니다. '구식 클래스'를 작성하더라도 묵시적으로 파생됩니다 object
.
새로운 스타일 클래스에는 super
새로운 C3 mro , 일부 마법적인 방법 등과 같은 구식 클래스에서 부족한 몇 가지 고급 기능이 있습니다 .
여기에는 매우 실용적이고 참 / 거짓의 차이가 있습니다. 다음 코드의 두 버전 간의 유일한 차이점은 두 번째 버전에서 Person 이 object 로부터 상속 한다는 것입니다 . 그 외에 두 버전은 동일하지만 결과가 다릅니다.
구식 수업
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>
>>>
새로운 스타일의 수업
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>
>>>
_names_cache
는 전달하는 모든 이름을 캐시 (향후 검색을 위해 저장)하는 사전입니다 Person.__new__
. 사전에 정의 된 setdefault 메소드는 키와 값의 두 가지 인수를 사용합니다. 키가 dict에 있으면 값을 반환합니다. dict에 없으면 먼저 두 번째 인수로 전달 된 값으로 설정 한 다음 반환합니다.
__new__()
항상 호출되며 항상 새로운 객체를 생성 한 다음 던집니다. 이 경우에는 a if
보다 바람직합니다 .setdefault()
.
__new__
실제로 구식 클래스에는 문제가 아니며 인스턴스 생성에 사용되지 않습니다 (정의처럼 특별한 것처럼 보이는 임의의 이름 일뿐입니다 __spam__
). 따라서 구식 클래스를 구성하면을 호출 __init__
하는 반면, 새 스타일 구성은 __new__
이름을 기준으로 싱글 톤 인스턴스에 통합하여 구성하고 __init__
초기화합니다.
새로운 스타일의 클래스 object
는 파이썬 2.2부터 (예를 들어 class Classname(object):
대신 class Classname:
) 상속 받아야합니다 . 핵심 변경 사항은 형식과 클래스를 통합하는 것이며, 이로 인한 부작용은 기본 제공 형식에서 상속 할 수 있다는 것입니다.
자세한 내용은 descrintro 를 읽으십시오 .
type(x)
. 내장 유형을 서브 클래스 화하지 않으면 새로운 스타일 클래스에서 볼 수있는 이점이없는 것 같습니다. 의 추가 유형 인 단점이 있습니다(object)
.