I have two questions regarding the behavior of running the below code. Why is __new__
even being called without instantiating an object? I thought __new__
controlled the creation of a new instance. Next, why does delattr
raise an AttributeError when hasattr
returns True for size?
class ShapeBase(type):
def __new__(cls, name, bases, attrs):
rv = super(ShapeBase, cls).__new__(cls, name, bases, attrs)
parents = [base for base in bases if isinstance(base, ShapeBase)]
# don't do anything unless this is a subclass of Shape
if not parents:
r开发者_运维百科eturn rv
print hasattr(rv, 'altitude') # prints True
print rv.altitude # prints 7
del rv.altitude # deletes altitude from rv
print hasattr(rv, 'size') # prints True
print rv.size # prints 5
delattr(rv, 'size') # raises AttributeError
return rv
class Shape(object):
__metaclass__ = ShapeBase
size = 5
class Triangle(Shape):
altitude = 7
__new__
of a metaclass controls the instantiation of a new class, not a new instance of that class. So, when you create the class Shape
with ShapeBase
as the metaclass, ShapeBase.__new__
is invoked.
For the second question delattr(rv, 'size')
(and del rv.size
) is failing because the attribute size
is a class attribute not an instance attribute which mean is part of the class __dict__
not the instance __dict__
.
And the hasattr
normally will return True
because it search for an attribute in all the parent classes of the object passed to it.
As for why your metaclass __new__
is called when the class body is evaluated think of it like this :
If you create an instance of a class the class
__new__
will be called when you create the instance, yes ? so the same should apply on class , a metaclass is a class of a class so the__new__
will be called when you create the class.
精彩评论