【发布时间】:2012-05-30 09:34:15
【问题描述】:
让我从定义我的目标开始:
-
启用没有默认值的抽象类成员(不是属性、方法或实例成员)的定义(不是 None 或其他一些魔法值,但如果未实现则会引发错误)。
李> 为 (1) 服务,创建一个可重用的抽象机制,使创建具有抽象成员的类变得微不足道,并且代码尽可能简洁。
能够将抽象类成员附加到父类(作为子类、元类或通过任何其他方式),其中在定义具体子类之前无需定义抽象成员。
到目前为止我得到了什么:
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' not in name)中,但这看起来既笨拙又脆弱。
有没有更好的方法来做到这一点?
【问题讨论】:
-
是的,有更好的方法。使用 Python 标准库中的 ABC module。
-
@agf,除了我的理解,它只允许抽象方法和属性,不允许抽象类成员。
标签: python abstract-class metaclass class-members