python - 将元类规则应用于所有后代而不是直接元类

标签 python abstract-class metaclass class-members

让我首先定义我的目标:

  1. 启用没有默认值(不是 None 或其他一些神奇值,但如果未实现则抛出错误)的抽象类成员(不是属性、方法或实例成员)的定义。

    <
  2. 为 (1) 服务,创建一个可重用的抽象机制,使创建具有抽象成员的类变得简单,并使执行此操作的代码最大限度地简洁。

  3. 能够将抽象类成员附加到父类(作为子类、元类或通过任何其他方式),其中在定义具体子类之前不需要定义抽象成员。

到目前为止我所得到的:

metaclass_lib.py:

class AbstractRequiredClassMembersMetaclass(type):

    def __new__(cls, name, bases, attrs):

        missed_members = []
        for class_member in cls.REQUIRED_CLASS_MEMBERS:
            if class_member not in attrs:
                missed_members.append(class_member)
        if missed_members:
            raise NotImplementedError('Class missing required members %s.' % missed_members)
        return super(AbstractRequiredClassMembersMetaclass, cls).__new__(cls, name, bases, attrs)



class _MakeRequiredClassMemebersMetaclass(object):

    existing_classes = {}

    def __call__(self, name, required_members):

        if name in _MakeRequiredClassMemebersMetaclass.exisiting_classes:
            if required_members != _MakeRequiredClassMemebersMetaclass.exisiting_classes[name].REQUIRED_CLASS_MEMBERS:
                raise RuntimeError('Class of name %s already defined with different required_members.' % name)
        else:
            NewClass = type(name, (AbstractRequiredClassMembersMetaclass,), {'REQUIRED_CLASS_MEMBERS' : required_members})
            _MakeRequiredClassMemebersMetaclass.exisiting_classes[name] = NewClass
        return _MakeRequiredClassMemebersMetaclass.exisiting_classes[name]

make_required_class_members_metaclass = _MakeRequiredClassMemebersMetaclass()

goods.py(用于说明的实现):

from metaclass_lib import make_required_class_members_metaclass

class AbstractGood(object):

    __metaclass__ = make_required_class_members_metaclass('AbstractGoodMeta', ('unit_measure',))

    def __init__(self):

        self.unit_price = None

    def total_cost(self, number_of_units):

        return self.unit_price * self.number_of_units



class DeliGood(AbstractGood):

    unit_measure = 'lbs'

    def __init__(self):

        self.sandwich_counter_product = False



class RefridgeratedGood(AbstractGood):

    unit_measure = 'package'

    def __init__(self):

        self.freezer_safe = False
        self.optimal_temp = '35'

这不起作用,因为元类在创建 AbstractGood type 对象期间被阻塞。问题是我希望所有具体商品定义类成员,但我不想在任何抽象基础中定义类成员。我能想到的就是让元类只执行 in attrs 检查关键字是否不在 name 中(例如 if 'Abstract' 不在 name),但这看起来很笨拙且脆弱。

有更好的方法吗?

最佳答案

也是一种 hack,但比检查名称更可靠。 您知道抽象基类没有基类 (或者在 python 2 中只有 object 类型)。所以你可以检查一下:)

class AbstractBase(object):
   class __metaclass__(type):
        def __new__(mcs, name, bases, dict_):
           if bases[0] is not object: # hack to not apply these on AbstractBase
                assert 'unit_measure' in dict_
           return type.__new__(mcs, name, bases, dict_)


class DeliGood(AbstractBase):
    unit_measure = 'lbs'

关于python - 将元类规则应用于所有后代而不是直接元类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10726676/

相关文章:

python - 在 Flask 中运行 Fabric 命令会阻止请求

Java 集合类型参数到数组

c# - 为什么在接口(interface)中有抽象类和抽象变量/方法?

python - 仅对子类使用元类

python - 为什么在这种情况下不使用元类?

python - 一种使 pandas 中的转置等转换更快的优雅方法

php - Unicode 到 PHP 执行

python - 哪个 SKLearn 接口(interface)定义了 .fit、.predict 等

c++ - Unresolved external (抽象类构造函数/析构函数)

python - Django 模型父链接的自定义相关名称?