24

我定义了一个Vector具有三个属性变量的类xyz。坐标必须是实数,但没有什么可以阻止您执行以下操作:

>>> 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。

建议?

4

5 回答 5

18

您必须问自己为什么要在设置这些值时测试类型。只需TypeError在任何碰巧遇到错误类型的计算中提出 a 即可。奖励:标准操作已经这样做了。

>>> 3.0 / 'abc'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for /: 'float' and 'str'
于 2010-09-20T08:41:50.280 回答
12

Duck Typing是 Python 中的常用方法。它应该适用于任何表现得像数字但不一定实数的东西。

在 Python 中的大多数情况下,不应显式检查类型。您获得了灵活性,因为您的代码可以与自定义数据类型一起使用,只要它们行为正确。

于 2010-09-20T08:44:24.353 回答
5

其他答案已经指出,在这里检查类型没有多大意义。此外,如果你的类是用纯 Python 编写的,它的速度不会很快。

如果您想要一个更 Pythonic 的解决方案 - 您可以使用如下属性设置器:

@x.setter
def x(self, value):
    assert isinstance(value, numbers.Real)
    self.__x = value

当您禁用调试或启用优化模式时,断言语句将被删除。

或者,您可以强制value在 setter 中使用浮点数。如果类型/值不可转换,则会引发异常:

@x.setter
def x(self, value):
    self.__x = float(value)
于 2010-09-20T08:47:50.873 回答
4

但是没有什么可以阻止人们做以下事情:

我相信试图阻止某人做这样的事情是不符合 Python 的。如果必须,那么在我看来,您应该可能使用 进行的任何操作期​​间检查类型安全性。Vector

引用 GVR:

我们都是成年人。

毕竟。有关更多信息,请参阅此问题及其答案。

我相信这里更有经验的 Pythonistas 可以给你更好的答案。

于 2010-09-20T08:41:14.087 回答
2

您不应该以这种方式提供类型安全。是的,有人可以通过提供您的容器无法工作的值来故意破坏您的代码 - 但这与其他语言相同。即使有人将正确的参数值放入方法或成员函数中,也不一定意味着它没有损坏:如果程序需要一个 IP 地址,但您传递了一个主机名,它仍然无法工作,尽管两者都可能是字符串。

我要说的是:Python 的思维方式本质上是不同的。鸭子打字基本上说:嘿,我不限于某些类型,而是界面或对象的行为。如果一个对象确实表现得像我所期望的那种对象,我不在乎 - 去吧。

如果您尝试引入类型检查,则基本上是在限制该语言最有用的功能之一。

话虽如此,您确实需要进行测试驱动开发,或至少进行单元测试。真的没有理由不使用动态语言来做这件事——它只是将检测(类型)错误的方式转移到构建过程中的另一个步骤,从编译时间到每天多次运行测试套件。虽然这看起来像是增加了工作量,但它实际上会减少调试和修复代码所花费的时间,因为它本质上是一种更强大的方法来检测代码中的错误。

但够了,我已经在胡说八道了。

于 2010-09-20T08:50:47.113 回答