2016-11-13 60 views
0

考慮下面的代碼的靜態屬性:使用元類訪問子

def print_name(*args, **kwargs): 

    cls = type(*args, **kwargs) 
    print "hello " + cls.name 
    return type.__new__(*args, **kwargs) 

class B(object): 
    __metaclass__ = print_name 
    name = 'animal' 

class C(B): 
    name = "zebra" 

class D(B): 
    name = "pig" 

我想要實現的是有功能print_name可以在B子類(C和d)打了個電話,讓它會打印名稱爲的靜態屬性。所以期望的輸出應該看起來像這樣 -

animal 
zebra 
pig 

非常感謝!

回答

2

在你print_name()功能,應更換此:

return type.__new__(*args, **kwargs) 

與此:

return cls 

這種方式,你會擺脫TypeError你看到的。

錯誤發生是因爲__new__的第一個參數必須是一個類型對象。 __new__的正確調用是:type.__new__(type, *args, **kwargs),但在您的情況下,實際上不需要兩次創建該類。

現在,即使使用此修復程序,您也不會在輸出中看到「斑馬紋」和「豬」,因爲您直接從type生成類B,這樣您的元類信息就會丟失。

你應該考慮這樣的事情:

class print_name(type): 

    def __new__(mcls, *args, **kwargs): 
     cls = super(print_name, mcls).__new__(mcls, *args, **kwargs) 
     print "hello " + cls.name 
     return cls 

這樣,B及其所有子類將是print_name型的,你的代碼將在每次創建一個子類時被正確執行。

(作爲一個方面說明,元類可以使不可能使用多重繼承,所以仔細考慮是否真的需要它們。)