Python中一个类的两个元类

时间:2019-02-26 03:24:53

标签: python

我创建了一个元类“ StructMeta”,用于在Python中引入自定义类型系统,详细信息如下。

from inspect import Signature, Parameter

class Descriptor():
    def __init__(self, name=None):
        self.name = name

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value

    def __get__(self, instance, cls):
        return instance.__dict__[self.name]

class Typed(Descriptor):
    ty = object
    def __set__(self, instance, value):
        if not isinstance(value, self.ty):
            raise TypeError('Expected %s' %self.ty)
        super().__set__(instance, value)

class Integer(Typed):
    ty = int

class Float(Typed):
    ty = float

class String(Typed):
    ty = str

class Positive(Descriptor):
    def __set__(self, instance, value):
        if value < 0:
            raise ValueError('Expected >= 0')
        super().__set__(instance, value)

class PosInteger(Integer, Positive):
    pass

class Sized(Descriptor):
    def __init__(self, *args, maxlen, **kwargs):
        self.maxlen = maxlen
        super().__init__(*args, **kwargs)

    def __set__(self, instance, value):
        if len(value) > self.maxlen:
            raise ValueError('TooBig')
        super().__set__(instance, value)

class SizedString(String, Sized):
    pass

def make_signature(names):
    return Signature([Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names])

class StructMeta(type):

    def __new__(cls, name, bases, clsdict):
        fields = [key for key, value in clsdict.items() if isinstance(value, Descriptor)]

        for name in fields:
            #print(type(clsdict[name]))
            clsdict[name].name = name

        clsobj = super().__new__(cls, name, bases, clsdict)
        sig = make_signature(fields)
        setattr(clsobj, '__signature__', sig)
        return clsobj

class Structure(metaclass = StructMeta):
    def __init__(self, *args, **kwargs):
        bound = self.__signature__.bind(*args, **kwargs)
        for name, value in bound.arguments.items():
            setattr(self, name, value)

现在,我希望我的类“ Stock”使用类型检查器元类以及抽象元类。这是不可能的,因为我最终将为Stock类拥有两个元类。我该如何解决这个问题?

class Stock(Structure):
        name =  SizedString(maxlen=9)
        shares =  PosInteger()
        price = Float()

        # @abstractmethod
        def us_stock:
           pass

有关自定义类型系统的更多详细信息,请参阅Python type checking system

0 个答案:

没有答案