Python __new__ 元类行为与继承
我对运行以下代码的行为有两个问题。为什么__new__
甚至在没有实例化对象的情况下被调用?我认为 __new__ 控制了新实例的创建。接下来,为什么当 hasattr
对于 size 返回 True 时,delattr
会引发 AttributeError ?
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
元类的 __new__ 控制新类的实例化,而不是该类的新实例。因此,当您创建以
ShapeBase
作为元类的Shape
类时,将调用ShapeBase.__new__
。__new__
of a metaclass controls the instantiation of a new class, not a new instance of that class. So, when you create the classShape
withShapeBase
as the metaclass,ShapeBase.__new__
is invoked.对于第二个问题,
delattr(rv, 'size')
(和del rv.size
)失败,因为属性size
是一个类属性不是实例属性,这意味着它是类__dict__
的一部分,而不是实例__dict__
的一部分。hasattr
通常会返回True
,因为它会在传递给它的对象的所有父类中搜索属性。至于为什么在评估类主体时调用元类
__new__
,可以这样想:For the second question
delattr(rv, 'size')
(anddel rv.size
) is failing because the attributesize
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 returnTrue
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 :