Python中的语义类型安全性

时间:2013-09-30 07:47:23

标签: python types type-safety

在我最近的项目中,我遇到了一个问题,即某些值经常被误解。例如,我计算一个波作为两个波的总和(我需要两个振幅和两个相移),然后在4个点采样。我将这四个值的元组传递给不同的函数,但有时我错误地传递波参数而不是采样点。

这些错误很难找到,因为所有的计算都没有任何错误,但在这种情况下,这些值完全没有意义,因此结果是错误的。

我现在想要的是某种语义类型。我想声明一个函数返回样本点而另一个函数等待样本点,并且我不会做任何会在没有立即出错的情况下与此声明冲突的事情。

在python中有什么办法吗?

2 个答案:

答案 0 :(得分:5)

我建议实现特定的数据类型,以便能够区分具有相同结构的不同类型的信息。 例如,您可以简单地将list子类化,然后在函数中在运行时进行一些类型检查:

class WaveParameter(list):
    pass

class Point(list):
    pass

# you can use them just like lists    
point = Point([1, 2, 3, 4])

wp = WaveParameter([5, 6])

# of course all methods from list are inherited
wp.append(7)
wp.append(8)

# let's check them
print(point)
print(wp)

# type checking examples
print isinstance(point, Point)
print isinstance(wp, Point)
print isinstance(point, WaveParameter)
print isinstance(wp, WaveParameter)

因此,您可以在函数中包含此类型检查,以确保将正确类型的数据传递给它:

def example_function_with_waveparameter(data):
    if not isinstance(data, WaveParameter):
        log.error("received wrong parameter type (%s instead WaveParameter)" %
                  type(data))
    # and then do the stuff

或只是assert

def example_function_with_waveparameter(data):
    assert(isinstance(data, WaveParameter))

答案 1 :(得分:2)

Pyhon的“语义类型”概念称为class,但如上所述,Python是动态类型的,因此即使使用自定义类而不是元组,也不会出现任何编译时错误 - 最好是你如果您的类的设计方式使得尝试使用一个而不是另一个会失败,那么将会出现运行时错误。

现在类不只是关于数据,它们也是关于行为的,所以如果你有执行波形特定计算的函数,这些函数可能会成为Waveform类的方法,而{{1}的同义词部分,这可能足以避免逻辑错误,例如将“波形”元组传递给期望“点”元组的函数。

总而言之:如果你想要一个静态类型的函数式语言,Python就不是正确的工具(Haskell可能是更好的选择)。如果你真的想/必须使用Python,尝试使用类和方法而不是元组和函数,它仍然不会在编译时检测到类型错误,但你可能会有更少的类型错误,并且这些类型错误将是在运行时检测到而不是产生错误的结果。