Подтвердить что ты не робот

Безопасность типов в Python

Я определил класс 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

... но это кажется не-питоновым.

Предложения?

4b9b3361

Ответ 1

Вы должны спросить себя, почему вы хотите проверить тип при настройке этих значений. Просто поднимите TypeError в любом вычислении, которое случается, чтобы наткнуться на неправильный тип . Бонус: стандартные операции уже делают это.

>>> 3.0 / 'abc'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for /: 'float' and 'str'

Ответ 2

Duck Typing - это обычный способ в Python. Он должен работать со всем, что ведет себя как число, но не обязательно действительное число.

В большинстве случаев в Python не нужно явно проверять типы. Вы получаете гибкость, потому что ваш код может использоваться с пользовательскими типами данных, если они ведут себя правильно.

Ответ 3

Но нечего делать, чтобы сделать следующее:

Я считаю, что пытаться помешать кому-то сделать что-то подобное не-питоновское. Если вам нужно, вы должны проверить безопасность типа во время любых операций, которые вы можете сделать, используя Vector, на мой взгляд.

Чтобы указать G.V.R:

Мы все взрослые.

в конце концов. См. Этот вопрос и его ответы для получения дополнительной информации.

Я уверен, что более опытные Pythonistas могут дать вам лучшие ответы.

Ответ 4

В других ответах уже указано, что здесь нет смысла проверять тип. Кроме того, ваш класс будет не очень быстрым, если он написан на чистом Python.

Если вы хотите больше pythonic-решения, вы можете использовать средства настройки свойств, например:

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

Оператор assert будет удален при отключении отладки или активации режима оптимизации.

В качестве альтернативы вы можете заставить value с плавающей запятой в установщике. Это вызовет исключение, если тип/значение не конвертируемо:

@x.setter
def x(self, value):
    self.__x = float(value)

Ответ 5

Вы не должны обеспечивать безопасность типа таким образом. Да, кто-то может преднамеренно разорвать ваш код, предоставив значения, для которых ваш контейнер не будет работать, но это то же самое с другими языками. И даже если кто-то поместил правильное значение для параметра в метод или функцию-член, не обязательно означает, что он не сломан: если программа ожидает IP-адрес, но вы передаете имя хоста, оно все равно не будет работать, хотя оба могут быть строки.

Я говорю: менталитет Python по своей сути отличается. Утка набирает в основном: "Эй, я не ограничена определенными типами, но интерфейсом или поведением объектов. Если объект действительно действует как объект, который я ожидаю, мне все равно - просто пойдите для него.

Если вы попытаетесь ввести проверку типов, вы в основном ограничиваете одну из самых полезных функций языка.

Говоря об этом, вам действительно нужно пройти тестирование, основанное на тестировании, или, по крайней мере, единичное тестирование. На самом деле нет оправдания, чтобы не делать это с динамическими языками - он просто перемещает ошибки (типа), которые обнаруживаются на другом этапе процесса сборки, вдалеке от времени компиляции до запуска набора тестов несколько раз в день. Хотя это кажется добавленным усилием, это фактически сократит время, затрачиваемое на отладку и исправление кода, поскольку это по своей сути более мощный способ обнаружения ошибок в вашем коде.

Но этого достаточно, я уже бессвязно.