开发者

Python __new__ metaclass behavior with inheritance

开发者 https://www.devze.com 2023-03-21 00:43 出处:网络
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. Ne

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消