私が持っている目標を定義することから始めましょう。
デフォルト値のない抽象クラス メンバー (プロパティ、メソッド、またはインスタンス メンバーではない) の定義を有効にします (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
)が、それはぎくしゃくして壊れやすいようです。
これを行うより良い方法はありますか?