2017-07-30 212 views
1

是否有可能從python(2.7)中派生類的靜態成員初始化基類的靜態成員?python靜態成員初始化從派生類的靜態成員值

也就是說,假設我有一堆的映射存儲在一個簡單的數據庫實體類:以下所有實體有一個名爲id字段規則

class EntityA(EntityBase): 
    entityName = 'EntA' # the name of the entity in the DB 
    ... 

class EntityB(EntityBase): 
    entityName = 'EntB' # the name of the entity in the DB 
    ... 

,並假設數據庫建立'id_ 實體名稱'。因此,'id_EntA'和'id_EntB'分別是EntityA和EntityB的數據庫中id字段的名稱。

現在,我想從(抽象)基類(EntityBase)只有一次產生這兩個名字,但我不能找到一個方法來做到這一點...

我想寫類似:

class EntityBase: 
    idFieldName = 'id_' + *derived-class*.entityName 
    ... 

我知道我可以寫一個簡單的函數,返回連接字符串,但我想這不是我每次調用該函數的時間進行評估。這應該是可能的,因爲構建idFieldName值所需的所有信息都存儲在靜態變量中。

+0

但是'idFieldName'是'entityBase'的一個* static *成員** ** –

+0

如果你想鉤入類的創建,請查看元類。 – jonrsharpe

+0

@Willem:是的,我只喜歡它從派生類的靜態成員的值中生成一次(在「編譯時」)......它有意義嗎? – Clonet

回答

0

你可以使用什麼是metaclass。元類是某個類所屬的類。

然後你可以使用:

class MetaEntityBase(type): 
    def __new__(meta, name, bases, dct): 
     if 'entityName' in dct: 
      dct['idFieldName'] = 'id_'+dct['entityName'] 
     return super(MetaEntityBase,meta).__new__(meta,name,bases,dct) 

然後,你可以寫:

class EntityBase: 
    __metaclass__ = MetaEntityBase 

,現在如果我們查詢EntityA.idFieldName,我們得到:

>>> EntityA.idFieldName 
'id_EntA' 

在這裏,我們使用了if聲明首先檢查dct。該dct是包含前初始化類成員的字典:所以它包含了所有方法,類字段等

因此,我們檢查,如果'entityName'是關鍵之一(這由此意味着在類級別,它是在某個地方定義的)。如果是這種情況,我們在dct'idFieldName'中添加一個新元素,該元素預先將entityNameid_對齊。當然,如果沒有這樣的屬性entityName

元類的__new__在的建設,而不是對象的施工執行,你可以定義一個else情況下該怎麼做。所以除非你動態地創建類,否則它只會被調用一次。

+0

謝謝!這是完美的!我不得不承認,我對Python中的元類沒有任何認識,但它似乎是一個非常強大的概念。 – Clonet

+0

有一個問題:我試圖註釋掉if ...(留下下面一行),我期望它能爲派生類工作,但不能用於基礎類(我的意思是,我想我可以實例化派生類類但不是基類),但它不適用於兩者...爲什麼? – Clonet

+0

@Clonet:因爲在這種情況下永遠不會創建「EntityBase」。因爲它會出錯。結果你不能從這個類中派生出來。一個骯髒的黑客可能是將'entityName'字段添加到'EntityBase'類,或者'__new__'方法中的一些檢查。 –