题
我已经定义了一个 Vector
具有三个属性变量的类: x
, y
和 z
. 。坐标必须是实数,但是没有什么可以阻止一个人进行以下操作:
>>> v = Vector(8, 7.3, -1)
>>> v.x = "foo"
>>> v.x
"foo"
我可以这样实施“类型安全”:
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
...但这似乎没有pythonic。
建议?
解决方案
您必须问自己为什么要测试设置这些值的类型。只是提高一个 TypeError
在任何偶然发现错误的计算中 价值 类型。奖金:标准操作已经这样做。
>>> 3.0 / 'abc'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for /: 'float' and 'str'
其他提示
鸭打字 是Python的通常方式。它应该与任何事情一起使用 行为 像一个数字,但不一定 是 一个真实数字。
在大多数情况下,在Python中,不应明确检查类型。您会获得灵活性,因为您的代码可以与自定义数据类型一起使用,只要它们正确地表现。
其他答案已经指出,在此处检查该类型并没有多大意义。此外,如果您的班级用Pure Python编写,那么您的班级将不会很快。
如果您想要更多的Pythonic解决方案 - 您可以使用属性设置器,例如:
@x.setter
def x(self, value):
assert isinstance(value, numbers.Real)
self.__x = value
当您禁用调试或启用优化模式时,将删除断言语句。
或者,您可以强迫 value
在设定器中浮点。如果类型/值不转换,这将引起异常:
@x.setter
def x(self, value):
self.__x = float(value)
但是没有什么可以阻止一个人做以下事情:
我相信试图阻止某人做类似的事情是不pythonic的。如果必须,则应检查类型安全 中 您可能会使用的任何操作 Vector
, , 在我看来。
引用GVR:
我们都是成年人。
毕竟。看到这个 问题 及其答案以获取更多信息。
我敢肯定,这里经验丰富的毕达斯塔斯人可以为您提供更好的答案。
您不应该以这种方式提供类型的安全性。是的,有人可以通过提供容器无法正常工作的值故意破坏您的代码 - 但与其他语言相同。即使有人将参数的正确值放在方法或成员函数中并不一定意味着它没有破坏:如果程序期望一个IP地址,但是您通过主机名,它仍然无法正常工作,尽管两者都可能是字符串。
我的意思是:Python的心态本质上不同。鸭子打字基本上说:嘿,我不仅限于某些类型,而是界面或对象的行为。如果一个物体确实像我期望的那种对象一样起作用,我不在乎 - 只是去做。
如果您尝试引入类型检查,则基本上是限制该语言最有用的功能之一。
话虽如此,您确实需要至少进行测试驱动的开发或单位测试。确实没有任何借口不使用动态语言进行操作 - 它只是在构建过程中将错误(类型)错误移动到另一个步骤,从编译时间到每天多次运行测试套件。尽管这似乎是增加的精力,但它实际上将减少在调试和修复代码上花费的时间,因为这是检测代码中错误的本质更强大的方法。
但是足够了,我已经在闲逛了。