fields['key'] = 'value'
メタクラスの機械が作動する前に実行します。
class foo(object):
var1 = 'bar'
def foobar(self):
pass
Pythonがclass
ステートメントにヒットすると、新しいローカル名前空間に入ります。
var1 = 'bar'
ステートメントを評価します。これはと同等ですlocals()['var1'] = 'bar'
次に、def foobar
ステートメントを評価します。これはと同等ですlocals()['var'] = the result of compiling the function
次にlocals()
、クラス名、継承されたクラス、およびメタクラスとともに、メタクラス__new__
メソッドに 渡します。例の場合、メタクラスは単純type
です。
次に、新しいローカル名前空間を終了__new__
し、外部名前空間から返されたクラスオブジェクトをという名前で貼り付けfoo
ます。
A.fields
クラスA
はすでに作成されており、上記のプロセスはにMeta
インストールfields
して実行されているため、コードは使用時に機能しますA
。
スーパーの実行時にスーパーに渡すようにsuper().fields
クラス名が定義されていないため、使用できません。B
つまり、必要になりますsuper(B).fields
が、 クラスの作成後にB
定義されます。
アップデート
質問に対する私のコメントへの返信に基づいて、あなたが望むことを実行するいくつかのコードがあります。
def MakeFields(**fields):
return fields
class Meta(type):
def __new__(mcs, name, bases, attr):
for base in bases:
if hasattr(base, 'fields'):
inherited = getattr(base, 'fields')
try:
attr['fields'].update(inherited)
except KeyError:
attr['fields'] = inherited
except ValueError:
pass
return type.__new__(mcs, name, bases, attr)
class A(metaclass=Meta):
fields = MakeFields(id='int',name='varchar')
class B(A):
fields = MakeFields(count='int')
class C(B):
pass
class Test(object):
fields = "asd"
class D(C, Test):
pass
print C.fields
print D.fields