2012-05-08 4 views
3

이 메타 클래스를 기반으로하는 클래스에 정의 된 모든 메소드가 기본적으로 클래스 메소드 (예 : @classmethod 장식 등을 필요로하지 않음)가되도록 메타 클래스를 작성하는 방법이 있습니까?Metaclass를 사용하여 클래스 메소드를 기본값으로 설정 하시겠습니까?

감사합니다.

편집 : 저는 Python 2.7.3에 관심이 있습니다. 누락을 용서해주십시오. 이 (2.7)

def m(name, bases, dct): 
    for k, v in dct.items(): 
     if type(v) is type(m): 
      dct[k] = classmethod(v) 
    return type(name, bases, dct) 

class A: 
    __metaclass__ = m 

    def foo(self): 
     print self 


A.foo() # <class '__main__.A'> 

답변

0

뭔가. 진짜 질문은 당신이 이것을하고 싶어하는 이유입니다. 나는 이것이 교육만을위한 것이라고 가정 할 것입니다. 실제로, 이것이 사용될 수있는 것이 무엇이든 명시 적으로 (즉, 메타 클래스를 사용하지 않고 @classmethod을 추가하는 것보다) 더 잘 수행 될 수 있습니다.

두 가지 옵션을 알고 있습니다. 클래스 정의를위한 맞춤 네임 스페이스 및 후 처리가 __new__입니다. 첫 번째 메소드는 매우 차갑고 어떤 경우에는 (예 : 메소드 정의의 순서를 기억하는 등) 피할 수 없지만, 후자는 더 간단하고 유연하며 실수로 여러 개의 할당을 동일한 이름으로 나눌 수없고 Python 2에서 사용할 수 있습니다. 당신의 목적은이 전 배제,하지만 난 사용 파이썬 3

사용자 정의 네임 스페이스를, 당신은 메타 클래스에서 __prepare__를 정의하고 돌아왔다 공급하기 위해 할 수있는 모든 사용자를 위해 그것을에서 떠날거야 사전 같은 객체 (Ferdinand Beyer는 주석에 언급 : collections에 정의 된대로 매핑 인터페이스가 충분 함). 이 경우 값이 callable인지 확인하려면 사전에 __setitem__을 무시하고, 그렇다면 에 저장하십시오. 아래 코멘트에 많은 것을 썼습니다. 아래 코드를 대폭 개선했습니다. Ferdinand Beyer는 callable(classmethod(...))이 거짓임을 알았고 agf는 @classmethod과 Python 3 호환성과의 불일치를 지적했습니다.

import types 

# Either this, in a dictionary class instanciated in __prepare__ 
# Again, Python 3 only 
def __setitem__(self, name, value): 
    if isinstance(value, types.FunctionType): 
     value = classmethod(value) 
    super().__setitem__(name, value) 

# __prepare__ would be: return AutomaticClassMethodNamespace() or something 

# Or this in the metaclass 
def __new__(mcls, clsname, bases, ns): 
    for name, value in ns.items(): 
     if isinstance(value, types.FunctionType): 
      ns[name] = classmethod(value) 
    # Any other metaclass behaviour 
+3

함수를 검사하는 표준 방법은 if ​​isinstance (v, types.FunctionType) :'입니다. 'm','k','v'보다 더 의미있는 이름을 사용하면 더 좋을 것입니다. – agf

+0

@agf : 나는 주문을 믿지 않는다. – georg

+0

나는 그 의견이 무엇을 의미하는지 생각하지 못합니다. 메타 클래스 함수의 이름을 변경한다고 가정합니다. 코드가 깨집니다. 함수 대신에'type'을 상속받은 클래스를 사용한다고 가정합니다. 코드가 깨집니다. 그래서 간접적으로 찾는 것이 아니라 실제 유형을 사용하는 것입니다. 특히 누군가에게 설명 할 때 의미있는 이름을 사용하는 것이 기본적인 상식입니다. – agf

3

물론 같은

+1

특별히'callable'이 아닌'types.FunctionType'을 사용해야합니다. 당신은 또한'과'를 의미합니다. 메타 클래스에서'__new__'을 어떻게 사용하면 동일한 이름의 다중 정의가 엉망이되는지 모르겠습니다. 각 식별자가 이미 단일 값으로 해석 된 사전을 얻었습니까? – agf

+0

레코드의 경우 :'__prepare__'에 의해 반환 된 객체는'dict'를 상속 할 필요가 없으며, 오직 "매핑 인터페이스를 지원"해야합니다 (예를 들어,'collections.MutableMapping' 추상 기본 클래스 사용). http : //docs.python을 참조하십시오.org3/py3k/reference/datamodel.html # customizing-class-creation –

+0

'classmethod'의 인스턴스는 호출 할 수 없으므로 추가 검사가 필요 없습니다. –

관련 문제