В чем разница между старыми и новыми классами стилей в Python?

в чем разница между старым стилем и новыми классами стилей в Python? Есть ли когда-нибудь причина использовать классы старого стиля в эти дни?

9 ответов


от http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes:

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

понятие класса (старого стиля) не связано с понятием типа: если x является экземпляром класса старого стиля, затем x.__class__ обозначает класс x, а type(x) всегда <type 'instance'>.

этот отражает тот факт, что все экземпляры старого стиля, независимо от их класс, реализуются с помощью одного встроенного типа, называемого пример.

классы нового стиля были введены в Python 2.2 для унификации понятий класса и типа. Класс нового стиля-это просто определяемый пользователем тип, не более и не менее.

если x является экземпляром класса нового стиля, то type(x) обычно то же самое, что x.__class__ (хотя это не гарантируется-a экземпляру класса new-style разрешено переопределять возвращаемое значение для x.__class__).

основной мотивацией для введения классов нового стиля является предоставление Единой объектной модели с полной метамоделью.

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

по соображениям совместимости, классы по-прежнему являются старомодными по умолчанию.

классы нового стиля создаются путем указания другого класса нового стиля (т. е. тип) как родительский класс или объект "тип верхнего уровня", если нет нужен другой родитель.

поведение классов нового стиля отличается от поведения классов старого стиля классы в ряде важных деталей в дополнение к тому, какой тип возвращается.

некоторые из этих изменений являются фундаментальными для новой объектной модели, например способ вызова специальных методов. Другие "исправления", которые не могли быть реализованным ранее для проблем совместимости, таких как метод порядок разрешения в случае множественного наследования.

Python 3 имеет только классы нового стиля.

независимо от того, если вы подкласс от object или нет, классы нового стиля в Python 3.


декларации-мудрый:

классы нового стиля наследуются от object или от другого класса нового стиля.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

классы старого стиля не делают.

class OldStyleClass():
    pass

важные изменения поведения между старыми и новыми классами стилей

  • супер добавил
  • MRO изменен (объяснено ниже)
  • дескрипторов добавил
  • новые объекты класса стиля не могут быть подняты, если не получены из Exception (пример ниже)
  • __slots__ добавил

MRO (порядок разрешения метода) изменен

он был упоминается в других ответах, но вот конкретный пример разницы между классическими MRO и C3 MRO (используется в новых классах стилей).

вопрос в том, в каком порядке атрибуты (которые включают методы и переменные-члены) ищутся в множественном наследовании.

классические классы сделайте первый поиск глубины слева направо. Остановка на первом матче. У них нет


классы старого стиля по-прежнему немного быстрее для поиска атрибутов. Обычно это не важно,но может быть полезно в Python 2, чувствительном к производительности.X код:

In [3]: class A:
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

In [4]: class B(object):
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

In [6]: aobj = A()
In [7]: bobj = B()

In [8]: %timeit aobj.a
10000000 loops, best of 3: 78.7 ns per loop

In [10]: %timeit bobj.a
10000000 loops, best of 3: 86.9 ns per loop

Гвидо написал внутренняя история о классах нового стиля, действительно отличная статья о новом стиле и старом стиле класса в Python.

Python 3 имеет только класс нового стиля, даже если вы пишете "класс старого стиля", он неявно производный от object.

классы нового стиля имеют некоторые дополнительные функции, отсутствующие в классах старого стиля, такие как super и новая C3 mro некоторые магические методы, и т. д.


вот очень практичная, истинная/ложная разница. Единственное различие между двумя версиями следующего кода заключается в том, что во второй версии Person наследует object. Кроме того, две версии идентичны, но с разными результатами:

1) старые классы

class Person():
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed1 is ahmed2
print ahmed1
print ahmed2


>>> False
<__main__.Person instance at 0xb74acf8c>
<__main__.Person instance at 0xb74ac6cc>
>>>

2) новый-стиль-классы

class Person(object):
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed2 is ahmed1
print ahmed1
print ahmed2

>>> True
<__main__.Person object at 0xb74ac66c>
<__main__.Person object at 0xb74ac66c>
>>>

классы нового стиля наследуются от object и должен быть написан как таковой в Python 2.2 и далее (т. е. class Classname(object): вместо class Classname:). Основное изменение заключается в объединении типов и классов, и приятный побочный эффект этого заключается в том, что он позволяет наследовать встроенные типы.

читать descrintro для получения более подробной информации.


новые классы стилей могут использовать super(Foo, self) здесь Foo класс а self - это экземпляр.

super(type[, object-or-type])

возвращает прокси-объект, который делегирует вызовы методов родителя или отпрыска класс тип. Это полезно для доступа к унаследованным методам, которые были переопределены в классе. Порядок поиска совпадает с порядком, используемым getattr (), за исключением того, что сам тип пропускается.

и в Python 3.X вы можете просто использовать super() внутри класса без параметров.


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