В чем разница между старым и новым стилем классов в Python? Когда я должен использовать один или другой?
Из новых и классических классов :
До Python 2.1 классы старого стиля были единственным вариантом, доступным пользователю.
Понятие класса (старого стиля) не связано с понятием типа: если
x
является экземпляром класса старого стиля, тоx.__class__
обозначает классx
, ноtype(x)
всегда<type 'instance'>
.Это отражает тот факт, что все экземпляры старого стиля, независимо от их класса, реализованы с помощью одного встроенного типа, называемого экземпляром.
Классы нового стиля были введены в Python 2.2, чтобы объединить понятия класса и типа . Класс нового стиля - это просто определенный пользователем тип, не больше, не меньше.
Если x является экземпляром класса нового стиля, то
type(x)
обычно он такой жеx.__class__
(хотя это не гарантировано - экземпляру класса нового стиля разрешено переопределять значение, возвращаемое дляx.__class__
).Основной мотивацией для введения классов нового стиля является предоставление единой объектной модели с полной метамоделью .
Он также имеет ряд непосредственных преимуществ, таких как возможность создавать подклассы для большинства встроенных типов или введение «дескрипторов», которые включают вычисляемые свойства.
По причинам совместимости классы по-прежнему в старом стиле .
Классы нового стиля создаются путем указания другого класса нового стиля (т. Е. Типа) в качестве родительского класса или объекта «тип верхнего уровня», если нет другого родителя.
Поведение классов нового стиля отличается от поведения классов старого стиля в ряде важных деталей в дополнение к тому, что возвращает тип.
Некоторые из этих изменений имеют фундаментальное значение для новой объектной модели, например, для вызова специальных методов. Другие являются «исправлениями», которые не могли быть реализованы ранее из-за проблем совместимости, например, порядок разрешения методов в случае множественного наследования.
В Python 3 есть только классы нового стиля .
Независимо от того, являетесь ли вы подклассом из
object
или нет, классы являются новым стилем в Python 3.
type(x)
. Если я не делю на подклассы встроенный тип, то, похоже, я не вижу никакого преимущества в классах нового стиля. Есть недостаток, который заключается в дополнительном наборе текста(object)
.super()
не работают на классах старого стиля. Не говоря уже о том, что, как говорится в этой статье, существуют фундаментальные исправления, такие как MRO, и специальные методы, что является более чем веским основанием для его использования.Декларация-накрест:
Классы нового стиля наследуются от объекта или другого класса нового стиля.
Классы старого стиля не делают.
Python 3 Примечание:
Python 3 не поддерживает классы старого стиля, поэтому любая из указанных выше форм приводит к классу нового стиля.
источник
object
.class AnotherOldStyleClass: pass
class A: pass
иclass A(): pass
строго эквивалентны. Первый означает «А не наследует ни один родительский класс», а второй означает «А не наследует ни один родительский класс» . Это очень похоже наnot is
иis not
Важные изменения поведения между старыми и новыми классами стиля
Exception
(пример ниже)__slots__
добавленнойMRO (порядок разрешения методов) изменен
Это было упомянуто в других ответах, но здесь приведен конкретный пример различия между классическим MRO и C3 MRO (используется в новых классах стиля).
Вопрос заключается в порядке поиска атрибутов (которые включают методы и переменные-члены) в множественном наследовании.
Классические занятия выполняют поиск в глубину слева направо. Остановись на первом матче. У них нет
__mro__
атрибута.Классы нового стиля MRO сложнее синтезировать в одном английском предложении. Это подробно объясняется здесь . Одним из его свойств является то, что базовый класс ищется только после того, как все его производные классы были. У них есть
__mro__
атрибут, который показывает порядок поиска.Новые объекты класса стиля не могут быть вызваны, если они не получены из
Exception
В Python 2.5 можно было создать много классов, а в Python 2.6 это было удалено. На Python 2.7.3:
источник
Классы старого стиля все еще немного быстрее для поиска атрибутов. Это обычно не важно, но может быть полезно в чувствительном к производительности коде Python 2.x:
источник
%timeit aobj.a
10000000 loops, best of 3: 66.1 ns per loop
%timeit bobj.a
10000000 loops, best of 3: 53.9 ns per loop
Гвидо написал «Внутреннюю историю о классах нового стиля» , действительно отличную статью о классах нового и старого стиля в Python.
Python 3 имеет только новый класс стиля. Даже если вы пишете «класс старого стиля», он неявно наследуется от
object
.У классов нового стиля есть некоторые расширенные функции, которых нет в классах старого стиля, такие как
super
новый C3 mro , некоторые магические методы и т. Д.источник
Вот очень практичная, истинная / ложная разница. Единственная разница между двумя версиями следующего кода заключается в том, что во второй версии Person наследуется от объекта . Кроме этого, две версии идентичны, но с разными результатами:
Уроки старого стиля
Уроки нового стиля
источник
_names_cache
это словарь, который кэширует (сохраняет для будущего поиска) каждое передаваемое вами имяPerson.__new__
. Метод setdefault (определенный в любом словаре) принимает два аргумента: ключ и значение. Если ключ находится в dict, он вернет свое значение. Если его нет в dict, он сначала установит для него значение, переданное в качестве второго аргумента, а затем вернет его.__new__()
он всегда вызывается, и он всегда создает новый объект, а затем выбрасывает его. В этом случаеif
предпочтительнее, чем.setdefault()
.__new__
на самом деле это не вещь для классов старого стиля, она не используется в конструкции экземпляра (это просто случайное имя, которое выглядит особенным, как определение__spam__
). Таким образом, создание класса старого стиля только вызывает__init__
, в то время как конструкция нового стиля вызывает__new__
(объединение с единичным экземпляром по имени), чтобы создать и__init__
инициализировать его.Классы нового стиля наследуются
object
и должны быть написаны как таковые в Python 2.2 и более поздних версиях (т.е.class Classname(object):
вместоclass Classname:
). Основное изменение заключается в унификации типов и классов, и приятным побочным эффектом этого является то, что он позволяет вам наследовать от встроенных типов.Читать descrintro для более подробной информации.
источник
Новые классы стилей могут использовать
super(Foo, self)
гдеFoo
класс иself
экземпляр.А в Python 3.x вы можете просто использовать
super()
внутри класса без каких-либо параметров.источник