다른 모든 형태의 중첩 된 클래스 정의와 마찬가지로 중첩 된 메타 클래스는 많은 종류의 "프로덕션 용도"에 대해 ("상속에 의한 경우를 제외하고 해당 메타 클래스를 다시 사용하지 않아도 괜찮 으면" 디버깅이나 인트로 스펙 션에서는 다소 불편할 수 있습니다.
기본적으로, 당신은 모듈에 정의 된 모든 사용자 정의 메타 클래스 무엇을 인 (자신의 __module__
및 __name__
속성에 따라 서로 undistiguishable 것을 끝낼거야 대신 메타 클래스에게 적절한 최상위 이름을주는 파이썬은 필요하다면 그들의 repr
을 형성하기 위해 사용한다.) 고려 :
>>> class Mcl(type): pass
...
>>> class A: __metaclass__ = Mcl
...
>>> class B:
... class __metaclass__(type): pass
...
>>> type(A)
<class '__main__.Mcl'>
>>> type(B)
<class '__main__.__metaclass__'>
IOW을, 당신은 (메타 클래스는, 클래스의 유형 기억) "클래스 A 인 유형"검사 할 경우, 당신은 명확하고 유용한 답변을 얻을 - 그것은 주요 모듈 Mcl
입니다. 그것은 이는 main
모듈 __metaclass__
의을 말한다, 그러나 그것은 심지어 사실이 아니다 : 당신이 "클래스 B 인 유형"검사 할 경우, 대답은 모두 유용하지 않습니다
>>> import __main__
>>> __main__.__metaclass__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__metaclass__'
>>>
... 거기 는 그런 것이, 실제로이다; 그 repr은 오해하기 쉽고별로 도움이되지 않습니다 ;-).
클래스의 repr은 본질적으로 간단하고 유용하며 일관된 규칙이지만 대부분의 경우 class
문이 모듈 범위에서 고유하지 않거나 전혀 모듈 범위에 있지 않습니다 (오히려 함수 또는 클래스 본문 내에서) 또는 존재하지 않아도 (클래스는 물론 class
문을 사용하지 않고 명시 적으로 메타 클래스를 호출하여 빌드 할 수 있습니다.)이 방법은 다소 오해의 소지가 있습니다 (가능한 한 최대 해결책은 피하는 것입니다. , 그 특별한 경우는, 그것을 사용함으로써 실질적인 이점을 얻을 수있는 경우를 제외하고).
이 같은 범위에서 두
class
문
>>> class A(object):
... def foo(self): print('first')
...
>>> x = A()
>>> class A(object):
... def foo(self): print('second')
...
>>> y = A()
>>> x.foo()
first
>>> y.foo()
second
>>> x.__class__
<class '__main__.A'>
>>> y.__class__
<class '__main__.A'>
>>> x.__class__ is y.__class__
False
가, 두 번째는 이름 (여기서, A
)를 리 바인드하지만, 기존 인스턴스 이름으로, 객체에 의해 이름의 첫 바인딩을하지 참조 : 예를 들어, 고려 - 두 클래스 객체가 남아 있으므로 인스턴스의 type
(또는 __class__
속성)을 통해서만 액세스 할 수있는 객체가있는 경우 (해당 객체가없는 경우 첫 번째 객체가 사라짐) 두 클래스가 동일한 이름과 모듈을 가지므로 같은 표현). 그러나 그들은 뚜렷한 대상이다. 클래스 또는 함수 본문에 중첩 된 클래스 또는 직접 (디버그 또는 내성 검사가 호출 될 경우) 비슷한 혼란을 일으킬 수있는 메타 클래스 (type
포함)를 호출하여 생성 된 클래스.
따라서 코드를 디버그하거나 다른 방법으로 내성 할 필요가없는 경우 메타 크라스를 중첩하는 것은 괜찮습니다. 누구든지이 단점을 이해한다면 누구나 함께 살 수 있습니다 (비록 멋진 코드를 사용하는 것만 큼 편리하지는 않지만). , 실제 이름은 - lambda
으로 코드화 된 함수를 디버깅하는 것과 마찬가지로 def
으로 코딩 된 디버깅과 같이 편리하지 않을 수 있습니다. lambda
과 def
의 유추를 통해 익명의 "중첩 된"정의는 완전히 단순한 메타 캐어 (no brainer)처럼 디버깅이나 인트로 스펙 션이 요구되지 않는다고 합리적으로 주장 할 수 있습니다.
파이썬 3에서는 "중첩 된 정의"가 작동하지 않습니다. class A(metaclass=Mcl):
에서와 같이 메타 클래스가 키워드 인수로 전달되어야하므로 본문에 __metaclass__
을 정의해도 아무런 효과가 없습니다. 파이썬 2 코드에서 중첩 된 메타 클래스 정의는 아마도 코드가 파이썬 3으로 포팅 될 필요가 없다는 것을 알고있는 경우에만 적합 할 것이라고 생각한다. (당신이이 포트를 훨씬 더 어렵게 만들고 있기 때문에 다시 말해, Python 3의 일부 버전이 속도, 기능 또는 제 3 자의 거대하고 강렬한 이점을 얻는 몇 년 안에는 존재하지 않을 "쓰레기"코드 인 목적을위한 메타 클래스 정의를 해제합니다. 파이썬 2.7 (파이썬 2의 마지막 버전)을 통한 파티 지원. 컴퓨팅의 역사는 우리에게 보여줍니다 당신이,가 버리는 것으로 예상
코드, "완전히 당신을 놀라게하고, 아마도 코드가 같은시기에 썼다 (약 20 년 후 여전히 존재의 사랑스러운 버릇이있다 나이를위한 "은 완전히 잊어 버렸습니다 ;-). 이것은 확실히 메타 클래스의 중첩 된 정의를 피할 것을 제안하는 것처럼 보일 것입니다.
아주 좋은 설명, 고마워. – cji
인상적인 대답. "당신은 의존하겠습니까?"와 직렬화에 약간 빠져 있습니다. –
'pickle'이 얼마나 많은지 잘 모르겠습니다. 산 세척은 잘 작동하는 것으로 보인다 [here] (http://gist.github.com/524744). –