1

私が持っている目標を定義することから始めましょう。

  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' not in name)が、それはぎくしゃくして壊れやすいようです。

これを行うより良い方法はありますか?

4

1 に答える 1

1

ハックでもありますが、名前を確認するよりも信頼できます。抽象基本クラスには基本クラスがない (またはobjectpython 2 の型しかない) ことがわかっています。だからあなたはそれをチェックすることができます:)

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'
于 2013-06-29T08:03:54.513 に答える