Python新元类行为与继承
关于运行下面代码的行为,我有两个问题。为什么在没有实例化对象的情况下调用Python新元类行为与继承,python,inheritance,metaprogramming,Python,Inheritance,Metaprogramming,关于运行下面代码的行为,我有两个问题。为什么在没有实例化对象的情况下调用\uuuuu new\uuuu?我想\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu控制了新。接下来,当hasattr返回大小的True时,为什么delattr会引发AttributeError 元类的\uuuuuuuuuuuuuuuuuuuuuu控制新类的实例化,而不是该类的新实例。因此,当您使用ShapeBase作为元类创建类Shape时
\uuuuu new\uuuu
?我想\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
控制了新。接下来,当hasattr
返回大小的True时,为什么delattr
会引发AttributeError
元类的
\uuuuuuuuuuuuuuuuuuuuuu
控制新类的实例化,而不是该类的新实例。因此,当您使用ShapeBase
作为元类创建类Shape
时,将调用ShapeBase.\uuuuu新的\uuuuu
。对于第二个问题delattr(rv,'size')
(和del rv.size
)失败,因为属性size
是类属性而不是实例属性,这意味着它是类\uuuuu dict\uuuuuu的一部分,而不是实例\uuuuu dict\uuuuu
而hasattr
通常会返回True
,因为它会在传递给它的对象的所有父类中搜索属性
至于为什么在计算类主体时调用元类\uuuuu new\uuuu
,可以这样想:
如果创建类的实例,则在创建实例时将调用类\uuuu new\uuuu
,是吗?因此,同样的方法也适用于类,元类是类的一个类,因此在创建类时将调用\uuuu new\uuuu
谢谢。我对这两个答案都投了较高的票,但由于你的答案是第一个并且回答了这两个问题,所以我将你的答案标记为正确。你的评论“除非这是Shape的子类,否则不要做任何事情”是误导性的,因为你所做的,是检查它是否继承了一个以ShapeBase
为元类的类。实际上,Shape
不是Shape的子类(即使issubclass(Shape,Shape)==True
),而Triangle
是。因此,代码可能是应该的,但是如果注释根本不存在,那么就不会那么混乱了。
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