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:
return 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
For the second question
delattr(rv, 'size')(anddel rv.size) is failing because the attributesizeis a class attribute not an instance attribute which mean is part of the class__dict__not the instance__dict__.And the
hasattrnormally will returnTruebecause 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 :