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
ShapeBaseas metaclass. As it is,Shapeis "not a subclass of Shape" (even thoughissubclass(Shape, Shape) == True), whileTriangleis. So, the code is maybe as it should be, but it would be less confusing if the comment wasn't there at all.