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

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

Самый питонический способ - не проверять тип... все напечатано уткой.

Какой канонический способ проверить тип в python?

Использование 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
Другие вопросы по тегам