Python type() или __class__, == или is

Я хочу проверить, является ли объект экземпляром класса и только этого класса (без подклассов). Я мог бы сделать то же самое с помощью:

obj.__class__ == Foo
obj.__class__ is Foo
type(obj) == Foo
type(obj) is Foo

Есть ли причины предпочесть одно другому? (различия в производительности, подводные камни и т. д.)

Другими словами: а) есть ли практическая разница между использованием __class__и type(x)? б) всегда ли объекты класса безопасны для сравнения с использованием is?


Обновление:Спасибо всем за отзывы. Я все еще озадачен тем, являются ли объекты класса синглтонами, мой здравый смысл говорит, что это так, но получить подтверждение было очень сложно (попробуйте поискать в Google «python», «class» и «unique» или «singleton») .

Я также хотел бы уточнить, что для моих конкретных нужд «более дешевое» решение, которое просто работает, является лучшим, так как я пытаюсь максимально оптимизировать несколько специализированных классов (почти достигнув точки где разумнее всего отказаться от Python и разработать этот конкретный модуль на C). Но причина вопроса заключалась в том, чтобы лучше понять язык, поскольку некоторые его функции слишком неясны для меня, чтобы я мог легко найти эту информацию. Вот почему я позволяю обсуждению немного расшириться вместо того, чтобы останавливаться на __class__ is, чтобы я мог услышать мнение более опытных людей.До сих пор это было очень плодотворно!

Я провел небольшой тест, чтобы оценить производительность четырех альтернатив. Результаты профайлера:

               Python  PyPy (4x)
type()    is   2.138   2.594
__class__ is   2.185   2.437
type()    ==   2.213   2.625
__class__ ==   2.271   2.453

Неудивительно, что равно лучше, чем == для всех случаев. type()лучше работал в Python (на 2% быстрее), а __class__лучше работал в PyPy (на 6% быстрее). Интересно отметить, что __class__ ==работает в PyPy лучше, чем type() is.


Обновление 2: многие люди, кажется, не понимают, что я имею в виду под «классом является синглтоном», поэтому я проиллюстрирую это примером:

>>> class Foo(object): pass
...
>>> X = Foo
>>> class Foo(object): pass
...
>>> X == Foo
False
>>> isinstance(X(), Foo)
False
>>> isinstance(Foo(), X)
False

>>> x = type('Foo', (object,), dict())
>>> y = type('Foo', (object,), dict())
>>> x == y
False
>>> isinstance(x(), y)
False

>>> y = copy.copy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True
>>> y = copy.deepcopy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True

Неважно, есть ли N объекты типа type, для данного объекта только один будет его классом, поэтому в этом случае безопасно сравнивать для ссылки. И поскольку эталонное сравнение всегда будет дешевле, чем сравнение стоимости, я хотел знать, верно ли мое утверждение выше. Я прихожу к выводу, что да, если только кто-то не представит доказательства обратного.

47
задан mgibsonbr 8 March 2012 в 18:10
поделиться