The following code doesn’t compile; it says
NameError: name ‘fields’ is not
defined
in the last line. Is it because __new__ isn’t called until after the fields assignment is reached? What should I do?
class Meta(type):
def __new__(mcs, name, bases, attr):
attr['fields'] = {}
return type.__new__(mcs, name, bases, attr)
class A(metaclass = Meta):
def __init__(self, name):
pass
class B(A):
fields['key'] = 'value'
EDIT:
I found that it’s not a problem with timing; it’s a problem with name hiding. Works fine if I write A.fields instead.
I’d like to know why I can’t use fields or super().fields.
The
fields['key'] = 'value'runs before the metaclass machinery kicks in.when python hits the
classstatement, it enters a new local namespace.it evaluates the
var1 = 'bar'statement. this is equivalent tolocals()['var1'] = 'bar'it then evaluates the
def foobarstatement. this is equivalent tolocals()['var'] = the result of compiling the functionIt then passes
locals(), along with the classname, the inherited classes and the metaclass to the metaclasses__new__method. In the example case, the metaclass is simplytype.It then exits the new local namespace and sticks the class object returned from
__new__in the outer namespace with the namefoo.Your code works when you use
A.fieldsbecause the classAhas already been created and the above process has hence been executed with yourMetainstallingfieldsinA.You can’t use
super().fieldsbecause the classnameBis not defined to pass to super at the time that super would run. that is that you would need it to besuper(B).fieldsbutBis defined after class creation.Update
Here’s some code that will do what you want based on your reply to my comment on the question.