2009-05-13 2 views
4

이것은 인터넷에서 발견 된 일부 코드입니다. 나는 그것이 어떻게 사용될 예정인지 모르겠습니다. 나는 멤버들에 enum 키/값을 채워 넣었지만 작동하지만,이 메타 클래스가 무엇인지 궁금합니다. 나는 그것이 ctypes와 관련이 있다고 가정하고 있지만, ctypes를 서브 클래 싱하는 것에 대한 많은 정보를 찾을 수 없다. EnumerationType이 열거 형을 사용하는 방식과 아무런 관련이 없다는 것을 알고 있습니다.하위 유형 ctypes - Python

from ctypes import * 

class EnumerationType(type(c_uint)): 
    def __new__(metacls, name, bases, dict): 
     if not "_members_" in dict: 
      _members_ = {} 
      for key,value in dict.items(): 
       if not key.startswith("_"): 
        _members_[key] = value 
      dict["_members_"] = _members_ 
     cls = type(c_uint).__new__(metacls, name, bases, dict) 
     for key,value in cls._members_.items(): 
      globals()[key] = value 
     return cls 

    def __contains__(self, value): 
     return value in self._members_.values() 

    def __repr__(self): 
     return "<Enumeration %s>" % self.__name__ 

class Enumeration(c_uint): 
    __metaclass__ = EnumerationType 
    _members_ = {} 
    def __init__(self, value): 
     for k,v in self._members_.items(): 
      if v == value: 
       self.name = k 
       break 
     else: 
      raise ValueError("No enumeration member with value %r" % value) 
     c_uint.__init__(self, value) 


    @classmethod 
    def from_param(cls, param): 
     if isinstance(param, Enumeration): 
      if param.__class__ != cls: 
       raise ValueError("Cannot mix enumeration members") 
      else: 
       return param 
     else: 
      return cls(param) 

    def __repr__(self): 
     return "<member %s=%d of %r>" % (self.name, self.value, self.__class__) 

And an enumeration probably done the wrong way. 

class TOKEN(Enumeration): 
    _members_ = {'T_UNDEF':0, 'T_NAME':1, 'T_NUMBER':2, 'T_STRING':3, 'T_OPERATOR':4, 'T_VARIABLE':5, 'T_FUNCTION':6} 
+0

코드가 코드로 형식화되어 있으므로 들여 쓰기를 조금 더 추가하고 싶습니다. 텍스트 영역 바로 위에있는 "101/010"버튼을 사용해보십시오. –

답변

4

메타 클래스는 클래스를 만드는 데 사용되는 클래스입니다. 이 방법으로 생각하십시오. 모든 객체에는 클래스가 있고 클래스도 객체입니다. 따라서 클래스에는 클래스가있을 수 있습니다.

http://www.ibm.com/developerworks/linux/library/l-pymeta.html

당신은 코드에서 몇 점을 볼 수 있습니다, 이것은 무엇을하고 있는지 이해합니다. "T_UNDEF" "T_NUMBER를"당신의 전역 사전에서이를 사용할 수 있습니다 :
_members_ = {'T_UNDEF':0, 'T_NAME':1, 'T_NUMBER':2, 'T_STRING':3, 'T_OPERATOR':4, 'T_VARIABLE':5, 'T_FUNCTION':6} 

globals()[key] = value 

여기 당신의 사전에 정의 된 모든 키를합니다. 당신이 당신의 열거의 인스턴스를 만들 때마다

def __init__(self, value): 
    for k,v in self._members_.items(): 
     if v == value: 
      self.name = k 
      break 

, 그것은 "값이"당신이 클래스를 초기화 할 때 허용 열거 이름의 목록에 있는지 확인합니다. 값을 찾으면 문자열 이름을 self.name으로 설정합니다.

c_uint.__init__(self, value) 

"ctypes 값"을 실제 c 부호없는 정수로 설정하는 실제 행입니다.

+0

감사. 이 기사는 모든 것을 설명했다. 나는 매일 새로운 것을 배울 것입니다. – Scott

3

실제로 이상한 클래스입니다.

또 다른 방법이 될 것입니다하지만 당신은, 그것은 올바른 사용 방법 :

는 그런 다음과 같이 사용할 수 있습니다

class TOKEN(Enumeration): 
    T_UNDEF = 0 
    T_NAME  = 1 
    T_NUMBER = 2 
    T_STRING = 3 
    T_OPERATOR = 4 
    T_VARIABLE = 5 
    T_FUNCTION = 6 

(즉, __new__에서 처음으로 6 선을위한 기능)

:

>>> TOKEN 
<Enumeration TOKEN> 
>>> TOKEN(T_NAME) 
<member T_NAME=1 of <Enumeration TOKEN>> 
>>> T_NAME in TOKEN 
True 
>>> TOKEN(1).name 
'T_NAME' 

from_param 방법은 INT 또는 Enumeration 개체 중 하나를 수용 방법을 작성하기위한, 편의를위한 것으로 보인다. 그것이 정말로 그 목적인지 확실하지 않습니다.

이 클래스는 외부 API로 작업 할 때 C 스타일의 enum을 사용하기위한 것이지만 매우 적은 이득을 얻는 것처럼 보입니다.

+0

글쎄, 내 LCD 프로젝트를위한 많은 리눅스 관련 플러그인이있는 빠른 표현 평가자를 얻었다. :) ctypes 모듈은 명시 적으로 열거 형을 나타내는 방법을 제공하지 않으므로 코드를 명시합니다. 내가 찾은 메타 클래스 없이도 동일한 작업을 수행 할 수 있습니다. 그것은 바로 세계를 제공하기위한 것입니다. 나는 파이썬을 5 년 넘게 사용 해왔고 나는 메타 클래스에 대해 전혀 알지 못했다. 나는 그것이 그것을 보았을 때 특정한 ctypes라고 생각했다. – Scott