История и дизайн Python: почему issubclass() вместо богатых сравнений?

В Python операторы сравнения - <, <=, ==, !=, >, >= - может быть реализовано для обозначения всего, что имеет отношение к классу реализации. В Python 2 это было сделано путем переопределения __cmp__и в Python 3 путем переопределения __lt__ и друзья. В чем преимущество наличия issubclass() встроенный метод вместо учета выражений, таких как bool < int (правда), int < object (правда), int <= int, или же int < float (ложный). В частности отмечу, что классы упорядочены issubclass() представляет собой частично упорядоченное множество в математическом смысле.

Python 3 эквивалент того, что я думаю, будет выглядеть так, как показано ниже. Этот код не заменяет issubclass() (хотя цикл по MRO достиг бы этого, верно?). Однако не будет ли это более интуитивно понятным?

@functools.total_ordering
class Type(type):
    "Metaclass whose instances (which are classes) can use <= instead issubclass()"
    def __lt__(self, other):
        try:
            return issubclass(self, other) and self != other
        except TypeError: # other isn't a type or tuple of types
            return NotImplemented
    def __eq__(self, other):
        if isinstance(other, tuple): # For compatibility with __lt__
            for other_type in other:
                if type(self) is type(other_type):
                    return False
            return True
        else:
            return type(self) is type(other)

Актуальный вопрос: В чем преимущество наличия встроенного метода issubclass() вместо учета выражений, таких как bool

3 ответа

Решение

Потому что это было бы против дзен Python: http://www.python.org/dev/peps/pep-0020/

Explicit is better than implicit.

Если вы посмотрите на следующую строку кода изолированно:

issubclass(a, b)

Совершенно очевидно, что a а также b переменные, содержащие классы, и мы проверяем, если a это подкласс b, И если они не содержат классов, вы будете знать.

Но, глядя на это

a < b

Не сказал бы тебе ничего. Вам нужно изучить окружающий код, чтобы определить, что он содержит классы, прежде чем вы поймете, что мы проверяем, a это подкласс b, И если, скажем, a=5 и b=6, он все равно будет работать "отлично".

Но Python гибкий, поэтому, если вы действительно этого хотите, вы можете реализовать базовый тип с таким поведением, как вы показали.

На самом деле - в стороне - например, преобладание операторов перегрузки в C++ является существенным недостатком языка (по крайней мере, на мой взгляд), потому что когда вы видите a + b с таким же успехом он может запустить ядерную ракету... пока вы не проверите типы a / b, посмотрите реализацию класса и + Реализация перегрузки оператора (если есть... и если нет, посмотрите, есть ли в родительском классе...., а если нет, посмотрите, есть ли родительский класс...)

Одно преимущество выделено жирным шрифтом:

issubclass(class, classinfo)

Верните true, если класс является подклассом (прямым, косвенным или виртуальным) classinfo. Класс считается подклассом самого себя. classinfo может быть кортежем объектов класса, и в этом случае будет проверяться каждая запись в classinfo. В любом другом случае возникает исключение TypeError.

Другое в том, что это описательно; не каждый, кто использует Python, математик.

Я бы сказал, что преимущество не функционально. Единственное техническое отличие состоит в том, что < это инфикс.

Но этот вопрос не о технических вещах. Это похоже на семантику и удобство чтения.

С помощью < будет означать порядок. Хотя иерархия классов может быть интерпретирована как "упорядоченная", она всегда будет приблизительной. Неочевидный для многих людей.

С помощью issubclass является более ясным, все еще простым и не поддающимся никакому другому толкованию, кроме того, что оно фактически делает: проверьте, object/classinfo это подкласс class,

Простой, простой, однозначный, эффективный. Это преимущества. Может быть, вы не можете / не можете воспользоваться ими. Но это уже личный вкус.

Другие вопросы по тегам