如果作为一个简化示例,我正在编写一个库来帮助人们对人口建模,我可能会有一个类,例如:
class Population:
def __init__(self, t0, initial, growth):
self.t0 = t0,
self.initial = initial
self.growth = growth
其中 t0 是日期时间类型。现在我想提供一种方法来确定给定时间的人口,无论是日期时间还是包含自 t0 以来的秒数的 float 。此外,调用者提供此类时间的数组是合理的(如果是这样,我认为假设它们都属于同一类型是合理的)。至少有两种方法可以实现此目的:
每种类型的方法
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 可能更有用。
请注意,有必要支持以 float 形式给出的时间,即使只有库本身使用此功能,例如,我可能会实现一种方法,该方法在更复杂的模型中找到固定点,其中浮点表示显然更可取.在此先感谢您的任何建议或建议。
最佳答案
我相信您可以在这里简单地坚持 Python 的 Duck Typing 哲学
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")
Default Case 应该是终止案例
- 如果连续的案例相互排斥,则按可能性排序。
- 通过抛出 Exception 来为意外做好准备。毕竟
错误不应该悄无声息地过去。
关于编写接受多种类型的库函数的 Pythonic 方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19365600/