Frage

Dies ist ein Code ich im Internet gefunden. Ich bin mir nicht sicher, wie es soll verwendet werden. Ich habe einfach gefüllt Mitglieder mit den Enum-Schlüssel / Werte und es funktioniert, aber ich bin gespannt, was diese metaclass geht. Ich gehe davon aus es etwas mit ctypes zu tun hat, aber ich kann nicht viele Informationen über Subklassifizieren ctypes finden. Ich weiß, EnumerationType ist nichts die Art und Weise tun Enumeration Ich verwende.

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}
War es hilfreich?

Lösung

Eine Metaklasse ist eine Klasse verwendeten Klassen zu erstellen. Denken Sie daran, auf diese Weise:. Alle Objekte haben eine Klasse, eine Klasse ist auch eine Aufgabe, daher macht es Sinn, dass eine Klasse eine Klasse haben kann

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

Um zu verstehen, was dies tut, Sie an einigen Punkten im Code suchen.

 _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

Hier nimmt er jeden definierte Schlüssel in Ihrem Wörterbuch: „T_UNDEF“ „T_NUMBER“ und macht sie in Ihrem Globals Wörterbuch verfügbar

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

Wenn Sie eine Instanz Ihrer Enum machen, prüft es, ob der „Wert“ in der Liste der zulässigen Enum-Namen, wenn Sie die Klasse initialisiert. Wenn der Wert gefunden wird, setzt sie den String-Namen self.name.

c_uint.__init__(self, value)

Dies ist die eigentliche Linie, die den „ctypes Wert“ auf einen tatsächlichen c unsigned integer setzt.

Andere Tipps

Das ist in der Tat eine seltsame Klasse.

Die Art und Weise Sie es verwenden ist richtig, obwohl eine andere Art und Weise wäre:

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

(Das ist, was die ersten 6 Zeilen in __new__ sind)

Dann können Sie es wie so verwenden:

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

Die from_param Methode scheint für Bequemlichkeit zu sein, Methoden zu schreiben, die entweder ein int oder ein Enumeration Objekt übernehmen. Nicht wirklich sicher, ob das wirklich sein Zweck erfüllt.

Ich denke, diese Klasse soll verwendet werden, wenn mit externen APIs der Verwendung c-Stil Aufzählungen zu arbeiten, aber es sieht aus wie eine ganze Menge Arbeit für sehr wenig Gewinn.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top