2011-07-15 16 views
0

以下のコードを実行する動作に関する2つの質問があります。オブジェクトをインスタンス化せずに__new__が呼び出されるのはなぜですか?私は__new__が新しいインスタンスの作成を制御したと思った。。次に、なぜdelattrサイズためはAttributeErrorときhasattr戻っを上げるのですか?メタクラスのPython __new__継承を伴う__new__メタクラスの動作

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 
+0

あなたのコメントは「これはシェイプのサブクラスでなければ何もしないでください」とは誤解を招いています。あなたが何をしているのか、あなたは「シェイプベース」をメタクラスとして持つクラスをチェックしています。そのままですが、 'Shape'は' issubclass(Shape、Shape)== True')でも "Shapeのサブクラスではありません"、 "Triangle"は "Shape"のサブクラスではありません。だから、コードはおそらくそうであるはずですが、そのコメントがまったく存在しない場合、混乱は少なくなります。 –

答えて

3

属性sizeは、平均インスタンス属性は、クラス__dict__ないインスタンス__dict__の一部であるクラスではない属性されるからです。

通常、hasattrは、渡されたオブジェクトのすべての親クラスの属性を検索するため、Trueを返します。

あなたはクラスのインスタンスを作成する場合は、インスタンスを作成するときに、クラス__new__が、呼び出されます:クラス本体はこのようにそれを考えると評価されたときに、あなたのメタクラス__new__が呼ばれている理由については

はい ?だからクラスに適用する必要があります、メタクラスはクラスのクラスですので、クラスを作成するときに__new__が呼び出されます。

+1

ありがとうございました。私は両方の答えをupvotedしかし、それが最初に来て両方の質問に答えたので、正しいとあなたの印を付けました。 –

4

__new__新しいクラスのインスタンス化ではなく、そのクラスの新しいインスタンスを制御します。したがって、クラスShapeShapeBaseでメタクラスとして作成すると、ShapeBase.__new__が呼び出されます。 2番目の質問delattr(rv, 'size')(及びdel rv.size)失敗しているため