Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python新元类行为与继承_Python_Inheritance_Metaprogramming - Fatal编程技术网

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