Reputation: 59594
I have this code:
class Attributes(object):
class __metaclass__(type):
def __init__(self, cls_name, cls_bases, cls_dict):
# super(Attributes.__metaclass__, self) # NameError: global name 'Attributes' is not defined
super(__metaclass__, self).__init__(
cls_name, cls_bases, cls_dict)
gives
NameError: global name '__metaclass__' is not defined
Why __metaclass__
variable is not found in the outer scope?
Upvotes: 3
Views: 279
Reputation: 59594
Looks like the answer is this:
Outer scope for a method is not class body, but outer function in which the class is contained or the module.
That's why in the case of
class Test():
attr_1 = 'smth'
def a_method(self):
attr_1 # not visible on this line
attr_1
is not visible inside method Test.a_method
And the solution is to define metaclass at global level:
class AttributesMeta(type):
def __init__(self, cls_name, cls_bases, cls_dict):
super(__metaclass__, self).__init__(
cls_name, cls_bases, cls_dict)
class Attributes(object):
__metaclass__ = AttributesMeta
Upvotes: 0
Reputation: 34307
try this instead
super(Attributes.__metaclass__, self).__init__(cls_name, cls_bases, cls_dict)
Upvotes: 2
Reputation: 59426
While creating a class, only its name is visible. Its contents does not exist yet until the class is finished being created. The parts inside the class, therefore, cannot access any fields of the class during creation. So you will need to use fully qualified names to denote that you want to access fields of the class
You are currently creating a class SimpleModel
and while doing so you are creating a class Attributes
and while doing so a class __metaclass__
. Since while you do this, the class SimpleModel
isn't existing yet, the method __init__
is not yet part of anything existing. It first gets created and then, later, will be made part of the class __metaclass__
. Hence it cannot know the identifier __metaclass__
. And since __metaclass__
also never becomes a global, when called, this identifier cannot be known.
That's the reason why you have no __metaclass__
in your scope at this point, but when later __init__
gets called, only a SimpleModel
is available via the global scope, so you can base your name on it: SimpleModel.Attributes.__metaclass__
.
Upvotes: 1