Pythonic способ проверить тип параметра
Я работаю над небольшим сторонним проектом для работы и сделал несколько классов и методов. Один из классов представляет полку в нашем инвентаре, а другой представляет каждую корзину на полке. У меня есть метод для добавления новой корзины на полку, и я добавил логику, чтобы убедиться, что передали объект Location до того, как он был добавлен на полку (сейчас я использую списки, пока разрабатываю, прежде чем переместить все в БД).
Однако я только что прочитал в книге по Python, что у меня обычно лучше обрабатывать исключения по мере их возникновения, чем добавлять дополнительный код. Я удалил логику, чтобы увидеть, какую ошибку я получу, но я ничего не получил, она позволила строку вместо объекта Location.
Есть ли более Pythonic способ установить тип параметра?
Что я имею для полки:
class CrossDock:
locations = []
def add_location(self, location):
if isinstance(location, Location): #if this is commented out it will take what ever is passed to it
self.locations.append(location)
else:
print("location parameter must be of type: Location. Parameter is of type" + str(type(location)))
Есть ли способ, которым я могу сделать это с блоком try/ Кроме?
4 ответа
Распространить исключение для звонящего. Это заставляет пользователей вашего класса исправлять недопустимый тип при неправильном использовании класса. Печать бесполезна, так как не требует соблюдения интерфейса.
class CrossDock(object):
def __init__(self):
self.locations = []
def add_location(self, location):
if isinstance(location, Location):
self.locations.append(location)
else:
raise TypeError("location must be Location, got: " +
repr(type(location)))
Исключение, которое вы можете получить, может произойти где-то еще в вашем коде, когда вы попытаетесь использовать экземпляр Location, но вместо этого найдете там что-то еще. Нет ничего плохого в проверке параметра, когда он исходит из ненадежного источника. Это помещает исключение в корень проблемы, а не в потенциально более сложную для диагностики вторичную позицию в вашем коде.
Вы можете сделать в значительной степени то, что имеете, только вызвать исключение, а не распечатать ошибку.
def add_location(self, location):
if not isinstance(location, Location):
tmpl = "location parameter must be of type: Location, got %s"
raise TypeError(tmpl % str(type(location)))
... do other processing here after guarding check ...
Этот тип проверки наиболее подходит, если у вас нет контроля над вызывающим кодом. Если вы просто хотите поймать ошибку программирования, которую вы сделали сами, вы можете просто использовать assert:
def add_location(self, location):
assert isinstance(location, Location), "location must be of type: Location"
... do other processing here
Совет против выполнения проверок типов параметров направлен на то, чтобы обеспечить максимальную гибкость в вашем коде, например, если кто-то хочет передать объект, который имеет те же методы, что и расположение Проверка на жестко запрограммированный тип вызовет исключение, даже если код может работать.
Самый питонический способ - не проверять тип... все напечатано уткой.
Использование assert
внутри блока try/ кроме
class Location():
pass
class CrossDock:
locations = []
def add_location(self, location):
try:
assert(isinstance(location, Location))
self.locations.append(location)
print("added")
except AssertionError:
print("error: Parameter is of type" + str(type(location)))
c = CrossDock()
loc = Location()
c.add_location("2")
c.add_location(loc)
Провалится на первом add_location
вызов
location parameter must be of type: Location. Parameter is of type<type 'str'>
added