2011-07-15 64 views
0

我對運行下面的代碼的行爲有兩個問題。爲什麼__new__甚至沒有實例化對象而被調用?我認爲__new__控制了新的實例的創建。接下來,爲什麼delattr增加AttributeErrorhasattr返回對於大小Python __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的子類,否則不要做任何事情」是誤導性的,因爲您正在做什麼,您是否在檢查它是否屬於ShapeBase類的元類。實際上,「Shape」不是「Shape的子類」(儘管'issubclass(Shape,Shape)== True'),而「Triangle」是。因此,代碼可能應該是這樣,但如果評論根本不存在,那麼它就不那麼令人困惑了。 –

回答

3

對於第二個問題delattr(rv, 'size')(和del rv.size)的失敗,因爲屬性size是一個類屬性不是實例屬性這意味着是類__dict__不是實例__dict__的一部分。

hasattr通常會返回True,因爲它在傳遞給它的對象的所有父類中搜索屬性。

至於爲什麼當類體被評估它這樣想你的元類__new__被稱爲:

如果你創建一個類時,你創建實例類__new__將被調用的一個實例,是嗎?所以類應該適用於類,元類是類的一個類,因此在創建類時將調用__new__

+1

非常感謝。我提出了兩個答案,但是標記爲正確,因爲它是第一個答案,並回答了這兩個問題。 –

4

元類的__new__控制新的類的實例,而不是這個類的一個新實例。因此,當您創建類ShapeShapeBase作爲元類時,將調用ShapeBase.__new__