今天小編就爲大家分享一篇Python 實現子類獲取父類的類成員方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
大家好,今天在寫代碼的時候,遇到了這樣一種情況。我有如下所示的幾個類用來存放程序配置(其實當做命名空間來用,同時感覺能夠繼承方便一點),
import os class Config: BASE_DIR = "/tmp" class TestConfig(Config): DATA_DIR = os.path.join(Config.BASE_DIR, "data")
然後我在子類中想要訪問父類的類成員變量,而且這兩個類都是隻有類成員變量。感覺目前我使用的方法笨一點,就是直接引用父類的名字,感覺這樣的方法不靈活,我想找一種方法,可以讓子類訪問到父類。
我在網上搜索了一下,找了這麼兩種方法,但是感覺都不怎麼符合我的需求:
1. 在子類方法中調用super(TestConfig, self)來獲取父類(我的類只有類成員變量,沒有self)
2. 通過子類的名字SubConfig.__bases__來獲取父類(我是在SubConfing這個子類內部執行相關語句的,會拋出SubConfig還未定義的NameError)
然後就沒有找到其他的辦法了,所以想來和大家請教一下,像我這種想法,有辦法可以實現嗎?應該怎麼做啊?這個問題問的可能比較傻,還請大家不要見怪。
@Python Yiyi
利用Python3 metaclass 實現
>>> import os >>> class M(type): @classmethod def __prepare__(metacls, name, bases, **kwds): d = dict() for base in bases: for key, value in base.__dict__.items(): if not key.startswith('_'): d[key] = value return d def __new__(cls, name, bases, namespace, **kwds): for base in bases: for key, value in base.__dict__.items(): if not key.startswith('_'): del namespace[key] return type.__new__(cls, name, bases, dict(namespace)) >>> class Config(metaclass=M): BASE_DIR = "/tmp" >>> class TestConfig(Config): DATA_DIR = os.path.join(BASE_DIR, "data") >>> TestConfig.DATA_DIR '/tmp\\data' >>> >>> TestConfig.__dict__ mappingproxy({'__doc__': None, '__module__': '__main__', 'DATA_DIR': '/tmp\\data'}) >>>
附上上述代碼的解釋,基本都來自於Python 語言參考中描述:
當執行類定義時,將執行以下步驟:
確定正確的元類
準備類的命名空間
執行類的主體
創建類對象
3.3.3.1. 確定正確的元類
3.3.3.2. 準備類的命名空間
確定正確的元類後,則開始準備類的命名空間。如果元類具有__prepare__屬性,那麼它以namespace = metaclass.__prepare__(name, bases, **kwds)形式調用(其中如果有額外的關鍵字參數,那麼它們來自類的定義)。
如果元類沒有__prepare__屬性,那麼類的命名空間初始化一個空的dict()實例。
3.3.3.3. 執行類的主體
類的主體(大體上)以exec(body, globals(), namespace)的方式執行。(從這裏可以看出,BASE_DIR找不到的原因是globals() 和namespace 中沒有BASE_DIR定義。解決辦法是將基類的成員拷貝到namespace中)
3.3.3.4. 創建類對象
類的命名空間通過執行類的主體創建完之後,通過調用metaclass(name, bases, namespace, **kwds)創建類對象(這裏傳遞過來的額外的關鍵字參數與傳遞給__prepare__的相同)。
以上這篇Python 實現子類獲取父類的類成員方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持神馬文庫。