2015-09-06 46 views
2

之間的引用說我有這樣的一組類:的Python:子類

class User(object): 

    def __init__(self, profile): 
     # ... 
     pass 

    @classmethod 
    def create_user(cls): 
     profile = Profile() 
     user = cls(profile) 

class Profile(object): 
    pass 

class SpecialUser(User): 
    pass 

class SpecialProfile(Profile): 
    pass 

每當我想繼承UserProfile,我需要排序的子類所有的人,因爲有上面的代碼,如果我做SpecialUser.create_user()它將是一個特殊用戶,但具有常規配置文件。

最簡單的解決方法是在User中創建一個可覆蓋的工廠函數,該函數創建相應的Profile。然而,這可能有點乏味。如果用戶有一個配置文件並像其他10個類一樣會怎麼樣?我是否必須重寫每個工廠函數?如果其他課程也互相引用會怎麼樣?所有這些課程是否也需要工廠功能?

我想過做這樣的事情:

class UserClasses(object): 

    class User(object): 

     def __init__(self, profile): 
      # ... 
      pass 

     @classmethod 
     def create_user(cls): 
      profile = cls.__parent__.Profile() 
      user = cls(profile) 

    class Profile(object): 
     pass 

class SpecialUserClasses(UserClasses): 

    class Profile(UserClasses.Profile): 
     pass 

結束語所有這些類另一個類中的意思是,如果我繼承外部類並重寫內部類中的一個,其他任何內部類,引用該類將自動使用重寫的一個。問題是,__parent__語法不存在,並且基於我的搜索,內部類不能輕鬆獲取其外部類。

我該如何獲得classmethod的功能,但對於相關類的組?

+1

你真的需要能夠處理「10個其他類也可以相互引用」嗎?如果在所有這些課程之間可以有一個任意的引用網頁,我不會看到你如何處理它,而不會讓人困惑和費力。 – BrenBarn

+0

這聽起來像[ACL的](http://www.limscoder.com/2009/11/role-based-security-with-python.html)是你在找什麼? – dawg

+0

@BrenBarn,在我的具體情況下,這些類將是[SQLAlchemy](http://www.sqlalchemy.org/)模型之間的相互關係(並且實際上是抽象的),因此它們需要具有像「用戶有配置文件」,「評論有用戶」等 – awesome

回答

2

您不一定需要使用可覆蓋的功能。你可能只是有一個重寫的屬性:

class User(object): 

    profile_class = Profile 

    def __init__(self, profile): 
     # ... 
     pass 

    @classmethod 
    def create_user(cls): 
     profile = cls.profile_class() 
     user = cls(profile) 

然後子類可以只是定義自己profile_class屬性,它會工作。但是,要做到這一點,任何用戶類必須在其對應的配置文件類(因爲用戶類引用類主體中的配置文件類)後定義。這限制了您可以使用的交叉引用的複雜性。然而,事實上,一個複雜的相互參照類系統往往令人困惑和脆弱。

+0

是否有一種方便的方式將profile_class,other_class,someother_class放入「工廠類」中並讓每個類都具有對該類的引用?我想通過使用裝飾器將每個類設置爲它的一個屬性。 – awesome

+0

@真棒:對不起,我不明白你的意思。什麼是「那個班級」? – BrenBarn