Тип безопасности в Python - PullRequest
24 голосов
/ 20 сентября 2010

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

... ноэто кажется непифоническим.

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

Ответы [ 5 ]

18 голосов
/ 20 сентября 2010

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

>>> 3.0 / 'abc'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for /: 'float' and 'str'
12 голосов
/ 20 сентября 2010

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

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

5 голосов
/ 20 сентября 2010

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

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

@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)
4 голосов
/ 20 сентября 2010

Но ничто не мешает сделать следующее:

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

Цитировать Г.В.Р .:

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

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

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

2 голосов
/ 20 сентября 2010

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

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

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

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

Но хватит этого, я уже болтаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...