Type safety in Python
我定义了一个
1 2 3 4 | >>> v = Vector(8, 7.3, -1) >>> v.x ="foo" >>> v.x "foo" |
我可以像这样实现"类型安全:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import numbers class Vector: def __init__(self, x, y, z): self.setposition(x, y, z) def setposition(self, x, y, z): for i in (x, y, z): if not isinstance(i, numbers.Real): raise TypeError("Real coordinates only") self.__x = x self.__y = y self.__z = z @property def x(self): return self.__x @property def y(self): return self.__y @property def z(self): return self.__z |
…但那似乎不是Python。
建议?
您必须问自己为什么要在设置这些值时测试类型。只需在任何计算中提高一个valuetype绊倒。奖励:标准操作已经做到了。
1 2 3 4 | >>> 3.0 / 'abc' Traceback (most recent call last): File"<stdin>", line 1, in ? TypeError: unsupported operand type(s) for /: 'float' and 'str' |
鸭子打字是Python常用的方法。它应该适用于任何类似于数字的行为,但不一定是实数。
在大多数情况下,在Python中不应该显式地检查类型。您获得了灵活性,因为您的代码可以与自定义数据类型一起使用,只要它们的行为正确。
其他答案已经指出,在这里检查类型没有多大意义。此外,如果你的类是用纯Python编写的,那么它就不会非常快。
如果你想要一个更为Python式的解决方案,你可以使用如下属性设置器:
1 2 3 4 | @x.setter def x(self, value): assert isinstance(value, numbers.Real) self.__x = value |
禁用调试或启用优化模式时,将删除assert语句。
或者,您可以在setter中强制
1 2 3 | @x.setter def x(self, value): self.__x = float(value) |
But there's nothing to stop one from doing the following:
我相信试图阻止某人做这种事是不可能的。如果必须,那么在我看来,在使用
引用G.V.R:
we are all adults.
毕竟。有关详细信息,请参阅此问题及其答案。
我相信这里经验丰富的Python师会给你更好的答案。
你不应该这样提供类型安全。是的,有人可以故意通过提供容器不起作用的值来破坏代码,但这与其他语言是一样的。即使有人将一个参数的正确值放入一个方法或成员函数中,并不一定意味着它没有被破坏:如果一个程序需要一个IP地址,但您传递了一个主机名,它仍然不能工作,尽管这两个参数都可能是字符串。
我要说的是:Python的思维方式本质上是不同的。duck输入法基本上是这样说的:嘿,我不局限于某些类型,而是对象的接口或行为。如果一个物体的行为真的像我所期望的那样,我不在乎——去追求它。
如果您试图引入类型检查,那么您基本上是在限制该语言最有用的特性之一。
也就是说,您确实需要进入测试驱动开发,或者至少是单元测试。确实没有理由不使用动态语言来完成这项工作——它只是将检测(类型)错误的方式转移到构建过程中的另一个步骤,从编译时间到每天多次运行测试套件。虽然这看起来像是额外的工作,但实际上它将减少调试和修复代码的时间,因为这是检测代码中错误的一种固有的更强大的方法。
但够了,我已经在闲逛了。