G. Однотипность не порок

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

Разработайте декоратор same_type, который производит проверку переменного количества позиционных параметров. В случае получения не одинаковых типов выводит сообщение “Обнаружены различные типы данных” и прерывает выполнение функции.

Примечание

Ваше решение должно содержать только функции.
В решении не должно быть вызовов требуемых функций.

Пример

Ввод

@same_type
def a_plus_b(a, b):
    return a + b


print(a_plus_b(3, 5.2) or 'Fail')
print(a_plus_b(7, '9') or 'Fail')
print(a_plus_b(-3, 5) or 'Fail')

Вывод

Обнаружены различные типы данных
Fail
Обнаружены различные типы данных
Fail
2

Ввод

@same_type
def combine_text(*words):
    return ' '.join(words)


print(combine_text('Hello,', 'world!') or 'Fail')
print(combine_text(2, '+', 2, '=', 4) or 'Fail')
print(combine_text('Список из 30', 0, 'можно получить так', [0] * 30) or 'Fail')

Вывод

Hello, world!
Обнаружены различные типы данных
Fail
Обнаружены различные типы данных
Fail

Решение

Достаточно простая задача. Нам нужно реализовать функцию-обертку, которая перед передачей параметров проверяла бы их на однотипность. Если все параметры одинаковы, то вызывала бы функцию-содержание и возвращала результат, в противном случае возвращала бы сообщение о неоднотипности данных.

Тут следует рассказать немного теории:
В python есть два основных способа узнать однотипность переменных:
1) запросить их тип c помощью type() и сравнить результат
2) проверить “совместимость” данных с помощью isinstance()

Разница между методами в строгости проверки. В то время как type() при сравнении требует строгого соответствия, isinstance() скажет, что bool и int это один и тот же тип.

В рамках решения этой задачи, никакой разницы между использованиями этих методов нет. Кроме того, если попробовать напрямую сравнить type(a) == type(b), ты мы получим предупреждение о том, что сравнивать типы нехорошо, и лучше использовать is, но возможно даже, стоит использовать isinstance(). Как относиться к этой ситуации и что использовать – решать вам. Случаи ложного срабатывания isinstance() довольно экзотические. В подавляющем большинстве случаев вы не заметите никакой разницы. Сам я предпочитаю type() из-за более строгой проверки

Итак, смысл алгоритма в том, чтобы сравнить тип первого элемента с типом остальных. С учетом наших знаний задача достаточно простая – узнаем тип первого элемента, в цикле перебираем типы оставшихся элементов и если находим отличный от первого, возвращаем ошибку.
Для проверки элементов можно использовать еще два разных способа – функцию all() или списочное выражение, выдающее на выходе множество типов данных, если длина множества больше единицы – значит у нас разнотипные данные.

Посмотреть код

Решение

Python
def same_type(func):
    def wrapper(*args):
        type_of_first = type(args[0])
        if all(type(item) == type_of_first for item in args[1:]):
            return func(*args)
        else:
            print('Обнаружены различные типы данных')
    return wrapper

Решение

Python
def same_type(func):
    def wrapper(*args):
        if len({type(item) for item in args}) != 1:
            print("Обнаружены различные типы данных")
            return False
        return func(*args)
    return wrapper
Подписаться
Уведомить о
guest
6 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
nmalkam
17.01.2024 09:13

{type(item) for item in args}
я правильно понимаю, что код выше строковое выражение??
не гуглится: строковое выражение python
если не сложно объясните, пожалуйста

Последний раз редактировалось 10 месяцев назад nmalkam ем
nmalkam
Ответить на  Сергей Клочко
17.01.2024 12:30

теперь дошло что создаём set
значит повторяться не будет

Сергей
Сергей
08.06.2024 09:39

Чекер (Flake8) и соответственно Яндекс ругается на конструкцию type(item) == a и не пропускает проверку. Избежал этого используя конструкцию type(item) is a. ну либо надо “включать”  isinstance()

Иван
Иван
31.07.2024 09:51

Спасибо за интересное решение (проверка длины множества типов входных данных):

if len({type(item) for item in args}) != 1: