質問
これは私がインターネットで見つけいくつかのコードです。私は、使用されることを意味しているかどうかはわかりません。私は単に列挙型のキー/値でのメンバーのを満たし、それが動作しますが、私はこのメタクラスはすべてに約あるか興味があります。私はそれがctypesのとは何かを持っていると仮定していますが、私はサブクラス化ctypesの上の多くの情報を見つけることができません。私はEnumerationTypeは何も私は列挙型を使用している方法をやっていません知っています。
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}
解決
メタクラスはクラスを作成するために使用されるクラスです。それをこのように考える:すべてのオブジェクトは、クラスを持って、クラスもオブジェクトであるため、それはクラスがクラスを持つことができるという意味になります。
。http://www.ibm.com/developerworks/linux /library/l-pymeta.htmlする
これがやっていることを理解するには、コード内のいくつかのポイントで見ることができます。
_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
「T_UNDEF」「T_NUMBERを」と、あなたのグローバル辞書でそれらが使用可能になります。 ここでは、辞書内のすべての定義されたキーになります。
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)
これは実際のCの符号なし整数に「ctypesの値」を設定実際の線である。
他のヒント
これは確かに奇妙なクラスです。
別の方法は次のようになりますが、あなたがそれを使用している方法は、正しいです。
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スタイルの列挙型で作業するときに使用されることを意図していると思うが、それは非常に少ない利益のために仕事の全体の多くのように見えます。