2013-10-14 51 views
6

如果作爲一個簡單的例子,我寫一個庫,以幫助人們模型的人羣,我可能有一個類,如:寫一個庫函數接受多種類型的pythonic方法?

class Population: 
    def __init__(self, t0, initial, growth): 
     self.t0 = t0, 
     self.initial = initial 
     self.growth = growth 

其中t0爲datetime類型。現在我想提供一種方法來確定給定時間的人口數量,無論是日期時間還是包含自t0以來的秒數的浮點數。此外,調用者提供一系列這樣的時間是合理的(如果是這樣,我認爲合理的假設它們都是相同類型的)。至少有兩種方法,我可以看到做到這一點:

每種類型

def at_raw(self, t): 
    if not isinstance(t, collections.Iterable): 
     t = numpy.array([t]) 
    return self.initial*numpy.exp(self.growth*t) 
def at_datetime(self, t): 
    if not isinstance(t, collections.Iterable): 
     t = [t] 
    dt = numpy.array([(t1-self.t0).total_seconds() for t1 in t]) 
    return self.at_raw(dt) 
  • 通用方法

    1. 方法

      def at(self, t): 
          if isinstance(t, datetime): 
           t = (t-self.t0).total_seconds() 
          if isinstance(t, collections.Iterable): 
           if isinstance(t[0], datetime): 
            t = [(t1-self.t0).total_seconds() for t1 in t] 
          else: 
           t = np.array([t]) 
          return self.initial*numpy.exp(self.growth*t) 
      

    要麼會的工作,但我我不確定哪一個是pythonic。我已經看到一些建議,類型檢查表明不好的設計會提示方法1,但由於這是一個供其他人使用的庫,方法2可能會更有用。

    注意,有必要支持給出花車時間,哪怕只有庫本身使用此功能,例如在浮點表示顯然是我有可能實現的,其根在更復雜的模型認定爲駐點的方法優選的。提前感謝您的任何建議或建議。

  • +2

    不知道你是否會得到比人們對這樣的問題的意見更好的東西。最重要的是,無論你選擇什麼都有很好的文檔記錄,並且最好在將來的版本中不會改變。我個人認爲第二個更好。 –

    +3

    閱讀PEP 443,然後在您的Python版本中重新實現它。它來自Python 3.4。 –

    +1

    我認爲向用戶提供某種類型的靈活性與您在檢查自己的數據類型時所遇到的可靠的糟糕代碼氣味完全不同。 – tripleee

    回答

    5

    我相信你可以簡單地用Python的鴨打字哲學這裏

    def at(self, t): 
        def get_arr(t): 
         try: # Iterate over me 
          return [get_arr(t1)[0] for t1 in t] 
         except TypeError: 
          #Opps am not Iterable 
          pass 
         try: # you can subtract datetime object 
          return [(t-self.t0).total_seconds()] 
         except TypeError: 
          #Opps am not a datetime object 
          pass 
         # I am just a float 
         return [t] 
        self.initial*numpy.exp(self.growth*np.array(get_arr(t))) 
    

    它的重要,堅持你如何排列個案

    1. 特定情況下應先於一般的情況下。

      def foo(num): 
          """Convert a string implementation to 
           Python Object""" 
          try: #First check if its an Integer 
           return int(num) 
          except ValueError: 
           #Well not an Integer 
           pass 
          try: #Check if its a float 
           return float(num) 
          except ValueError: 
           pass 
          #Invalid Number 
          raise TypeError("Invalid Number Specified") 
      
    2. 默認情況應終止情況

    3. 如果連續的情況下,是相互排斥的,由相似性排序。
    4. 通過引發異常來爲意外做準備。畢竟Errors should never pass silently.
    相關問題