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






Я в основном пытаюсь преобразовать переменную в то, чем она должна быть, и пропустить или выбросить соответствующее исключение, если это не удается.
def factorial(num):
"""Computes the factorial of num."""
try:
num = int(num)
except ValueError, e:
print e
else:
...
Это скорее зависит от того, что я пишу, и от того, как туда попадает результат. 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, которая всегда указывает на правильную строку кода. Это не совсем так. Если ваша функция выполняет операцию с некоторыми данными экземпляра, которые были установлены ранее, может быть очень сложно определить, почему значение имеет неправильный тип.
Почему это неправильный тип отличается от того, что на самом деле существование неправильного типа. Если ваша логика замучена и сложна, и вы не можете определить места, где установлены переменные, вам необходимо переосмыслить свой алгоритм. Действительно. Заявления о присвоении должны быть очевидными. У них есть =, и они - возможно - самые важные утверждения, потому что они изменяют состояние ваших вычислений. Я не уверен, что понимаю, что является сложным, если у вас нет проблем с поиском операторов присваивания.
assert int(num) == numэто проливает больше света на предмет, поэтому, на мой взгляд, это должен быть принятый ответ
Для вычислений, таких как сумма, факториал и т. д., Подойдут встроенные проверки типов pythons. Вычисления закончатся upp вызовом Добавлять, мул и т. д. Для типов, и если они сломаются, они все равно сгенерируют правильное исключение. Применяя свои собственные проверки, вы можете аннулировать рабочий ввод.
Я почти никогда не применяю никаких проверок, если только я не думаю, что есть вероятность, что кто-то может подумать, что они могут пройти какой-то X, который приведет к совершенно сумасшедшим результатам.
В другой раз я проверяю, когда я принимаю несколько типов в качестве аргумента, например, функция, которая принимает список, может принять произвольный объект и просто заключить его в список (если это еще не список). Поэтому в этом случае я проверяю тип - не для того, чтобы что-либо применять - просто потому, что я хочу, чтобы функция была гибкой в том, как она используется.
Только потрудитесь проверить, есть ли у вас провальный unit-тест, который заставляет вас это делать.
Также рассмотрите "EAFP" ... Это способ Python!
Немного взгляда на то, как с этим справляется другой язык, может добавить некоторую ценность. Помню, что для Perl я использовал этот модуль - http://search.cpan.org/dist/Params-Validate/, который избавляет разработчика от большого количества проверок параметров. Я искал что-то подобное в python и наткнулся на это: http://www.voidspace.org.uk/python/validate.html Я не пробовал. Но я полагаю, что стремление к стандартному способу проверки параметров по всей кодовой базе приводит к предварительной настройке ожиданий проверки параметров для всей команды.
Я предпочитаю ничего не печатать. Либо оставьте исключение в покое, либо создайте что-нибудь другое. печать сбивает с толку.