Pregunta

Esto es código que encontré en internet. No estoy seguro de cómo está destinado a ser utilizado. Simplemente llena miembros con las llaves / valores de enumeración y funciona, pero tengo curiosidad lo que este metaclase se trata. Estoy suponiendo que tiene algo que ver con ctypes, pero no puedo encontrar mucha información sobre ctypes de subclases. Sé EnumerationType no está haciendo nada la forma en que estoy usando Enumeración.

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}
¿Fue útil?

Solución

Una metaclase es una clase usada para crear clases. Piénsalo de esta manera:. Todos los objetos tienen una clase, una clase es también un objeto, por lo tanto, tiene sentido que una clase puede tener una clase

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

Para entender lo que está haciendo esto, se puede ver en algunos puntos en el código.

 _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

A continuación se tarda cada llave se define en el diccionario: "T_UNDEF" "T_NUMBER" y los pone a disposición en su diccionario globales

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

Siempre que se realice una instancia de su enumeración, se comprobará para ver si el "valor" está en la lista de nombres de enumeración permisibles al inicializar la clase. Cuando se encuentra el valor, se establece el nombre de la cadena de self.name.

c_uint.__init__(self, value)

Esta es la línea real que establece el "valor ctypes" a un c entero sin signo real.

Otros consejos

Esto es de hecho una clase rara.

La forma en que lo está utilizando es correcta, aunque de otra manera sería:

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

(Eso es lo que los primeros 6 líneas en __new__ son para)

A continuación, se puede usar de esta manera:

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

El método from_param parece ser por conveniencia, para los métodos de escritura que aceptan ya sea un entero o un objeto Enumeration. En realidad, no estoy seguro si eso es realmente su propósito.

Creo que esta clase está destinado a ser utilizado cuando se trabaja con las API externas las enumeraciones uso de estilo C, pero parece que una gran cantidad de trabajo para muy poca ganancia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top