如果,作为一个简化的例子,我正在编写一个图书馆来帮助人们模拟人群,我可能会有一个类,如:
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)
通用方法
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可能会更有用。
请注意,有必要支持以浮点数给出的时间,即使只有库本身使用此功能,例如我可能会实现一个方法,该方法在更复杂的模型中找到固定点,其中浮点表示显然更可取。提前感谢任何建议或建议。
答案 0 :(得分:5)
我相信你可以在这里坚持使用Python的Duck Typing Philosophy
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)))
重要的是,你如何订购案件
具体案例应先于一般案件。
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")
默认情况应该是终止案例
Errors should never pass silently.