2011-09-01 19 views
0

編輯:有一些混淆,但我想問一個關於Python中面向對象設計的常見問題。Python中from_ <type>的繼承

考慮一類,可以讓你的數據值映射到計數或頻率:

class DataMap(dict): 
    pass 

現在考慮一個子類,它可以讓你從數據列表構建一個直方圖:

class Histogram(DataMap): 
    def __init__(self, list_of_values): 
     # 1. Put appropriate super(...) call here if necessary 
     # 2. Build the map of values to counts in self 
     pass 

現在考慮一個類,可以讓你製作一個平滑的概率質量表,而不是一個Histogram

class ProbabilityMass(DataMap): 
    pass 

什麼是允許ProbabilityMass從無論是Histogram或值列表構造最好的辦法?我使用C++編程「長大」,在這種情況下,我會使用重載的構造函數。在Python我想用這樣的:

  • 的構造函數多個參數(所有,但這些應該==無)
  • 我定義from_Histogram和from_list方法

在第二種情況(我相信這是更好的),允許from_list方法使用Histogram構造函數中的共享代碼的最佳方法是什麼? A ProbabilityMass表格與Histogram表格幾乎相同,但它被縮放以便所有值的總和爲1.0。

如果您遇到類似問題,請分享您的專業知識!

+0

奧利弗,這個問題已被問過其他時間,雖然我很難找出正確的關鍵字來找到他們現在。基本上,使用'staticmethod'來調用構造函數作爲替代構造函數。 – agf

+0

@agf我應該定義兩個靜態方法(ProbabilityMass.from_list和ProbabilityMass.from_histogram)嗎?或者,如果他們中的一個使用__init__方法?或者也許有一些「構造函數重載」機器或標準我不知道(也許這是你的意思是「替代構造函數」)? – user

+0

如果其中一個明顯是「默認」/最通用的那個,則將其用作__init__。如果兩者都不是,你可以選擇一個作爲'__init__',或者你可以將通用代碼分解爲'__init__',並且在進行預處理之後都有靜態方法調用它。 (請確保在docstring中注意不要直接調用構造函數)。 – agf

回答

3

首先,如果你認爲你想@staticmethod,你幾乎總是不會。這個函數不是類的一部分,在這種情況下,它應該只是一個自由函數,或者它是類的一部分,但不是綁定到一個實例,它應該是@classmethod。您命名的構造函數是@classmethod的最佳人選。

另外請注意,你應該從B通過super()調用A.__init__,否則多重繼承可以咬你壞。

class A: 
    def __init__(self, data): 
     self.values_to_counts = {} 
     for val in data: 
      if val in self.values_to_counts: 
       self.values_to_counts[val] += 1 
      else: 
       self.values_to_counts[val] = 1 
    @classmethod 
    def from_values_to_counts(cls, values_to_counts): 
     self = cls([]) 
     self.values_to_counts = values_to_counts 
     return self 

class B(A): 
    def __init__(self, data, parameter): 
     super(B, self).__init__(data) 
     self.parameter = parameter 
    def print_parameter(self): 
     print self.parameter 

在這種情況下,你不需要一個B.from_values_to_counts,從A繼承,它會返回B一個實例,因爲這是它如何被調用。

如果您需要在B中執行更復雜的初始化,您可以使用super(),這看起來與您在實例中使用時的方式非常相似。畢竟,classmethod實際上並不比instancemethod更復雜,其中im_self屬性被分配給類本身。

class A: 
    def __init__(self, data): 
     self.values_to_counts = {} 
     for val in data: 
      if val in self.values_to_counts: 
       self.values_to_counts[val] += 1 
      else: 
       self.values_to_counts[val] = 1 
    @classmethod 
    def from_values_to_counts(cls, values_to_counts): 
     self = cls([]) 
     self.values_to_counts = values_to_counts 
     return self 

class B(A): 
    def __init__(self, data, parameter): 
     super(B, self).__init__(data) 
     self.parameter = parameter 
    def print_parameter(self): 
     print self.parameter 
    @classmethod 
    def from_values_to_counts(cls, values_to_counts): 
     self = super(B, cls).from_values_to_counts(values_to_counts) 
     do_more_initialization(self) 
     return self 
+0

不錯。可能希望將缺少的'return'添加到'from_values_to_counts'(我知道這只是一個示例,但不想誤導任何人)。 – agf

+0

「在這種情況下,您不需要B.from_values_to_counts,它從A繼承」我想要一個from_values_to_counts_and_parameter方法。該方法執行兩件事(設置values_to_counts變量和參數變量)。我知道類方法(他們在文章中提到);我也希望能夠解決這個問題。對於像概率質量表這樣的數據結構(可以通過值列表或直方圖來定義),定義構造函數或靜態/類方法的最佳方法是什麼? – user

+0

@agf:在我的編輯中得到了。和其他一些位和機器人。 – SingleNegationElimination