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



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

911   9  

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.

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

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

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 некоторые магические методы, и т. д.

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

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.

Comments

    Ничего не найдено.