Какую валидацию ввода я должен выполнять над моими функциями/методами python?

Мне интересно, сколько людей на передней панели делают в Python, которые они пишут.

Вот несколько примеров простых функций:

def factorial(num):
    """Computes the factorial of num."""

def isPalindrome(inputStr):
    """Tests to see if inputStr is the same backwards and forwards."""

def sum(nums):
    """Same as the built-in sum()... computes the sum of all the numbers passed in."""

Насколько тщательно вы проверяете входные значения перед началом вычислений и как вы выполняете проверку? Вы бросаете какое-то частное исключение, если ввод неисправен (например, BadInputException, определенный в том же модуле)? Вы только начинаете свой расчет и вычисляете, что в какой-то момент будет генерироваться исключение, если бы были переданы плохие данные (например, "asd" для факториала)?

Когда переданное значение должно быть контейнером, вы проверяете не только контейнер, но и все значения внутри него?

Как насчет таких ситуаций, как factorial, где то, что передавалось, может быть конвертировано в int (например, float), но при этом вы можете потерять точность?

Ответы

Ответ 1

Для вычислений, таких как сумма, факториал и т.д., проверки встроенных типов питонов будут выполнены. Вычисления приведут к тому, что upp вызовет добавить, mul и т.д. Для типов, и, если они сломаются, они все равно будут выкидывать правильное исключение. Соблюдая свои собственные проверки, вы можете недействить в противном случае рабочий ввод.

Ответ 2

I assert что абсолютно необходимо.

Важно: что абсолютно необходимо. Некоторые люди перепробовали вещи.

def factorial(num):
    assert int(num)
    assert num > 0

Не совсем правильно. долгое время также является юридической возможностью.

def factorial(num):
    assert type(num) in ( int, long )
    assert num > 0

Лучше, но все же не идеально. Многие типы Python (например, рациональные числа или числовые объекты) также могут работать в хорошей факториальной функции. Трудно утверждать, что объект имеет базовые целочисленные свойства, не будучи слишком конкретным и устраняя будущие неопытные классы из соображений.

Я никогда не определяю уникальные исключения для отдельных функций. Я определяю уникальное исключение для значимого модуля или пакета. Обычно, однако, просто класс Error или что-то подобное. Таким образом, приложение говорит except somelibrary.Error,e:, которое касается всего, что вам нужно знать. Мелкозернистые исключения становятся суетливыми и глупыми.

Я никогда этого не делал, но я вижу места, где это может понадобиться.

assert all( type(i) in (int,long) for i in someList ) 

Как правило, обычные проверки типа Python работают нормально. Они находят почти все исключительные ситуации, которые имеют значение почти все время. Когда что-то не соответствует типу, Python вызывает TypeError, который всегда указывает на правильную строку кода.

BTW. Я добавляю только утверждения во время разработки, если я абсолютно уверен, что функция будет злоупотреблять. Я иногда добавляю утверждения позже, когда у меня есть unit test, который не работает неясным образом.

Ответ 3

Я пытаюсь написать docstring, указав, какой тип параметра ожидается и принят, и я не проверяю его явно в моих функциях.

Если кто-то хочет использовать мою функцию с любым другим типом, его ответственность за проверку того, что его тип эмулирует один, я принимаю достаточно хорошо. Может быть, ваш факториал можно использовать с каким-то обычным длинным типом, чтобы получить то, о чем вы бы не подумали? Или, может быть, ваша сумма может использоваться для конкатенации строк? Почему вы должны запрещать это путем проверки типа? Это не C, так или иначе.

Ответ 4

Я в основном пытаюсь преобразовать переменную в то, что она должна быть, и пропустить или выбросить соответствующее исключение, если это не сработает.

def factorial(num):
    """Computes the factorial of num."""
    try:
        num = int(num)
    except ValueError, e:
        print e
    else:
        ...

Ответ 5

Это зависит от того, что я пишу, и как получается выход. Python не имеет публичной/частной защиты других OO-языков. Вместо этого существуют соглашения. Например, внешний код должен вызывать только методы объектов, которые не имеют префикса подчеркиванием.

Поэтому, если я пишу модуль, я бы проверял все, что не было создано из моего собственного кода, то есть любые вызовы общедоступных методов/функций. Иногда, если я знаю, что проверка является дорогостоящей, я делаю ее togglable с kwarg:

def publicly_accessible_function(arg1, validate=False):
  if validate:
    do_validation(arg1)
   do_work

Внутренние методы могут выполнять валидацию с помощью assert, который может быть полностью отключен, когда код выходит из разработки и в производство.

Ответ 6

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

В другой раз я проверяю, когда я принимаю несколько типов для аргумента, например функцию, которая принимает список, может принимать произвольный объект и просто переносить его в список (если он еще не является списком). Поэтому в этом случае я проверяю тип - не для того, чтобы обеспечить что-либо - только потому, что я хочу, чтобы функция была гибкой в ​​том, как она используется.

Ответ 7

Постарайтесь проверить, нет ли у вас отказоустойчивого модульного теста.

Также рассмотрим EAFP"... Это путь Python!

Ответ 8

Немного о перспективах того, как справляется другой язык, может добавить некоторую ценность. Для Perl я помню, используя этот модуль - http://search.cpan.org/dist/Params-Validate/, который выгружает много параметров для проверки разработчика. Я искал что-то подобное в python и наткнулся на это: http://www.voidspace.org.uk/python/validate.html Я не пробовал. Но я предполагаю, что стремление к стандартному способу проверки параметров во всей кодовой базе приводит к предварительной настройке ожиданий проверки параметров по всей команде.