История и дизайн 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
,
Простой, простой, однозначный, эффективный. Это преимущества. Может быть, вы не можете / не можете воспользоваться ими. Но это уже личный вкус.