Сколько проверки входных данных я должен сделать для моих функций / методов Python? - PullRequest
15 голосов
/ 15 декабря 2008

Меня интересует, сколько людей делают предварительную проверку на 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 (например, с плавающей точкой), но при этом вы можете потерять точность?

Ответы [ 8 ]

10 голосов
/ 15 декабря 2008

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

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

6 голосов
/ 15 декабря 2008

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

5 голосов
/ 15 декабря 2008

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

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

4 голосов
/ 15 декабря 2008

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

def factorial(num):
    """Computes the factorial of num."""
    try:
        num = int(num)
    except ValueError, e:
        print e
    else:
        ...
2 голосов
/ 15 декабря 2008

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

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

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

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

1 голос
/ 15 декабря 2008

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

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

0 голосов
/ 30 сентября 2011

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

0 голосов
/ 14 октября 2010

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

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

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