Question

Ceci est un code que je trouve sur Internet. Je ne sais pas comment il est destiné à être utilisé. J'ai simplement rempli membres avec les touches ENUM / valeurs et cela fonctionne, mais je suis curieux de ce que ce métaclasse est tout au sujet. Je suppose qu'il a quelque chose à voir avec ctypes, mais je ne trouve pas beaucoup d'informations sur ctypes de sous-classement. Je sais EnumerationType ne fait rien la façon dont je me sers Enumeration.

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}
Était-ce utile?

La solution

Une méta-classe est une classe utilisée pour créer des classes. Pensez à cette façon. Tous les objets ont une classe, une classe est aussi un objet, par conséquent, il est logique qu'une classe peut avoir une classe

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

Pour comprendre ce que cela fait, vous pouvez regarder quelques points dans le code.

 _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

Ici, il prend toutes les clés définies dans votre dictionnaire: « T_UNDEF » « T_NUMBER » et les met à disposition dans votre dictionnaire GLOBALS

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

Chaque fois que vous faites une instance de votre ENUM, il vérifiera si la « valeur » est dans la liste des valeurs possibles pour les noms de ENUM lors de l'initialisation de la classe. Lorsque la valeur est trouvée, elle définit le nom de chaîne à self.name.

c_uint.__init__(self, value)

est la ligne réelle, qui définit la « valeur en ctypes » pour un entier non signé c réelle.

Autres conseils

C'est en effet une classe bizarre.

La façon dont vous utilisez est correct, bien que d'une autre manière serait:

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

(C'est ce que les 6 premiers lignes sont pour __new__)

Ensuite, vous pouvez l'utiliser comme ceci:

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

La méthode semble être from_param pour des raisons pratiques, les méthodes d'écriture qui acceptent soit un int ou un objet Enumeration. Pas vraiment sûr que ce soit vraiment son but.

Je pense que cette classe est destiné à être utilisé lorsque vous travaillez avec des API externes pour les énumérations utilisation c-style, mais il semble que beaucoup de travail pour un gain très peu.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top