yay!メタクラスの使用のためだけには工夫されていないメタクラスの実際のアプリケーション!予期せぬプロパティがクラス定義に現れた場合に投げられるメタクラスを書くことができます。私たちがする必要があるのは、プログラマーが実際にそれを使用することだけです。クラス自体が定義されているときに私たちのチェックが実行されます:私たちも、インスタンス化することをしない方法を
class RequiredFieldsMeta(type):
_interface = {'company_name', 'num_employees'}
def __new__(cls, clsname, bases, attrs):
for field in RequiredFieldsMeta._interface:
if field not in attrs:
raise AttributeError(
'Class %s missing required property %s'
% (clsname, field))
for name in attrs:
if not isdunder(name) and name not in RequiredFieldsMeta._interface:
raise AttributeError(
'Class %s has extra property %s'
% (clsname, name))
return super(RequiredFieldsMeta, cls).__new__(cls, clsname, bases, attrs)
# Works fine:
class MongoCompany(metaclass=RequiredFieldsMeta):
company_name = 'Mongo Inc.'
num_employees = 100
# Throws AttributeError:
class ESyCompany(metaclass=RequiredFieldsMeta):
extra_prop = 'foobar'
Here's迅速なデモ
注意。
編集:私の編集では、私は関数is_dunder
を参照しています。これは、name.startswith('__')
や正規表現、あるいはあなたが望むものであれば簡単です。プログラマではなく、Pythonがクラスに入れたプロパティを取り除いている限りです。
EDIT 2:ちょうど楽しみのために、ここで私たちのチェックの2、より多くの "エレガント"(ただし以下の特定)の実装は、次のとおりです。
def __new__(cls, clsname, bases, attrs):
attr_names = {a for a in attrs if not is_dunder(a)}
if attr_names.difference(RequiredFieldsMeta._interface):
raise AttributeError('Class %s has extra properties' % clsname)
if RequiredFieldsMeta._interface.difference(attr_names):
raise AttributeError('Class %s missing required properties' % clsname)
return super(RequiredFieldsMeta, cls).__new__(cls, clsname, bases, attrs)
それとも単に:
def __new__(cls, clsname, bases, attrs):
attr_names = {a for a in attrs if not is_dunder(a)}
if attr_names != RequiredFieldsMeta._interface:
raise AttributeError(
'Class %s does not match the required interface' % clsname)
return super(RequiredFieldsMeta, cls).__new__(cls, clsname, bases, attrs)
最初にあなたは[継承](http://www.python-course.eu/python3_inheritance.php)の概念に精通していますか? – Skam
必要なさまざまなメソッドで 'throw NotImplementedError'sから継承する" interface "クラスを作成できます。 –
@MateenUlhaqプログラマが "interface"クラスよりも多くの属性をサブクラスに追加するのを妨げることはありません。 – kakarukeys