Сколько проверок ввода я должен делать для моих функций / методов 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 до факториала)?

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

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
15
0
3 685
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

Я предпочитаю ничего не печатать. Либо оставьте исключение в покое, либо создайте что-нибудь другое. печать сбивает с толку.

S.Lott 15.12.2008 14:27

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

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

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

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

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

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

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

Важно: что важно для абсолютно. Некоторые люди слишком много тестируют.

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

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

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, которая всегда указывает на правильную строку кода.

КСТАТИ. Я добавляю утверждения только во время разработки, если я абсолютно уверен, что функцией будут злоупотреблять. Иногда я добавляю утверждения позже, когда у меня есть модульный тест, который непонятным образом не работает.

> Когда что-то не того типа, Python вызывает ошибку TypeError, которая всегда указывает на правильную строку кода. Это не совсем так. Если ваша функция выполняет операцию с некоторыми данными экземпляра, которые были установлены ранее, может быть очень сложно определить, почему значение имеет неправильный тип.

Nathan 14.10.2010 14:06

Почему это неправильный тип отличается от того, что на самом деле существование неправильного типа. Если ваша логика замучена и сложна, и вы не можете определить места, где установлены переменные, вам необходимо переосмыслить свой алгоритм. Действительно. Заявления о присвоении должны быть очевидными. У них есть =, и они - возможно - самые важные утверждения, потому что они изменяют состояние ваших вычислений. Я не уверен, что понимаю, что является сложным, если у вас нет проблем с поиском операторов присваивания.

S.Lott 14.10.2010 14:14
assert int(num) == num
endolith 22.07.2015 03:03

это проливает больше света на предмет, поэтому, на мой взгляд, это должен быть принятый ответ

Sнаđошƒаӽ 04.01.2016 17:05
Ответ принят как подходящий

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

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

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

Только потрудитесь проверить, есть ли у вас провальный unit-тест, который заставляет вас это делать.

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

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

Другие вопросы по теме