Действительно ли распространено в Python продолжать тестировать на значения типа при работе способом ООП?
class Foo():
def __init__(self,barObject):
self.bar = setBarObject(barObject)
def setBarObject(barObject);
if (isInstance(barObject,Bar):
self.bar = barObject
else:
# throw exception, log, etc.
class Bar():
pass
Или я могу использовать более свободный подход, как:
class Foo():
def __init__(self,barObject):
self.bar = barObject
class Bar():
pass
Нет, на самом деле в подавляющем большинстве случаев не проверяют значения типов, как в вашем втором подходе. Идея заключается в том, что клиент вашего кода (т.е. другой программист, использующий ваш класс) должен иметь возможность передать любой тип объекта, который имеет все соответствующие методы или свойства. Если он не является экземпляром какого-то конкретного класса, то это прекрасно; ваш код никогда не должен знать разницы. Это называется утиной типизацией, из-за пословицы "Если она крякает как утка и летает как утка, то это может быть и утка" (ну, это не совсем пословица, но суть я уловил)
Одно из мест, где вы можете часто видеть это, это стандартная библиотека, с любыми функциями, которые обрабатывают ввод или вывод файлов. Вместо того чтобы требовать реальный объект file
, они берут все, что реализует метод read()
или readline()
(в зависимости от функции), или write()
для записи. На самом деле вы часто увидите это в документации, например, в tokenize. generate_tokens
, на который я случайно взглянул сегодня:
Генератор
generate_tokens()
требует один аргумент, readline, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и методreadline()
встроенных файловых объектов (см. раздел File Objects). Каждый вызов функции должен возвращать одну строку ввода в виде строки.
Это позволяет вам использовать объект StringIO
(например, файл в памяти) или что-то более странное, например, диалоговое окно, вместо реального файла.
В своем собственном коде просто обращайтесь к любым свойствам объекта, которые вам нужны, и если это не тот тип объекта, то одного из нужных вам свойств не будет, и это вызовет исключение.
Если вашей альтернативой проверке типа является обработка исключений else, содержащая обработку исключений, то вам действительно стоит подумать о том, чтобы набрать текст на один уровень выше, поддерживая столько объектов с методами, которые вам требуются из ввода, и работая внутри попробовать. Затем вы можете исключить (и исключить как можно более конкретно) это. Конечный результат не будет отличаться от того, что у вас есть, но будет намного более универсальным и питоническим.
На все остальное, что нужно было сказать о самом вопросе, является ли это общепринятой / хорошей практикой или нет, я думаю, Дэвид дал превосходный ответ.
Я думаю, что хорошей практикой является проверка input на тип. Разумно предположить, что если вы попросили пользователя указать один тип данных, он может указать другой, поэтому вы должны написать код для защиты от этого.
Однако, кажется, что это пустая трата времени (как на написание, так и на выполнение программы) на проверку типа входных данных, которые программа генерирует независимо от входных данных. Как и в сильно типизированном языке, проверка типа не важна для защиты от ошибки программиста.
В общем, проверяйте ввод, но не более того, чтобы код мог работать без проблем, а пользователи не задавались вопросом, почему они получили исключение, а не результат.
Я согласен с некоторыми ответами выше, в том смысле, что я обычно никогда не проверяю тип от одной функции к другой.
Однако, как уже говорилось, все, что принимается от пользователя, должно быть проверено, и для таких вещей я использую регулярные выражения. Приятным моментом в использовании регулярных выражений для проверки пользовательского ввода является то, что вы можете не только проверить, что данные имеют правильный формат, но и разобрать их в более удобную форму, например, как строку в словарь.