Вопрос:

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

python class oop types new-style-class

216268 просмотра

8 ответа

140496 Репутация автора

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

Автор: Readonly Источник Размещён: 10.09.2008 06:01

Ответы (8)


540 плюса

87420 Репутация автора

Решение

Из 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__(хотя это не гарантировано - экземпляру класса нового стиля разрешено переопределять значение, возвращаемое для x.__class__).

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

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

По причинам совместимости классы по-прежнему в старом стиле .

Классы нового стиля создаются путем указания другого класса нового стиля (т. Е. Типа) в качестве родительского класса или объекта «тип верхнего уровня», если нет другого родителя.

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

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

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

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

Автор: Mark Cidade Размещён: 10.09.2008 06:02

10 плюса

564 Репутация автора

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

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

Автор: Halo Размещён: 28.10.2008 09:54

297 плюса

184680 Репутация автора

Декларация-накрест:

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

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

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

class OldStyleClass():
    pass

Python 3 Примечание:

Python 3 не поддерживает классы старого стиля, поэтому любая из указанных выше форм приводит к классу нового стиля.

Автор: Mark Harrison Размещён: 30.07.2009 01:21

40 плюса

1948 Репутация автора

Классы старого стиля все еще немного быстрее для поиска атрибутов. Это обычно не важно, но может быть полезно в чувствительном к производительности коде Python 2.x:

В [3]: класс А:
   ...: def __init __ (self):
   ...: self.a = "привет"
   ...: 

В [4]: ​​класс B (объект):
   ...: def __init __ (self):
   ...: self.a = "привет"
   ...: 

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

В [8]:% timeit aobj.a
10000000 циклов, лучшее из 3: 78,7 нс на цикл

В [10]:% timeit bobj.a
10000000 циклов, лучшее из 3: 86,9 нс на цикл
Автор: xioxox Размещён: 12.07.2010 11:26

36 плюса

1108 Репутация автора

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

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

У классов нового стиля есть некоторые расширенные возможности, которых нет в классах старого стиля, такие как superи новый C3 mro , некоторые магические методы и т. Д.

Автор: Xiao Hanyu Размещён: 24.04.2013 01:41

8 плюса

92631 Репутация автора

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

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

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

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

Автор: jamylak Размещён: 30.04.2013 08:28

24 плюса

2946 Репутация автора

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

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>
>>>
Автор: ychaouche Размещён: 09.10.2013 01:40

221 плюса

177006 Репутация автора

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

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

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

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

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

Классические классы выполняют поиск в глубину слева направо. Остановись на первом матче. У них нет __mro__атрибута.

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

Классы нового стиля MRO сложнее синтезировать в одном английском предложении. Это подробно объясняется здесь . Одним из его свойств является то, что базовый класс ищется только после того, как все его производные классы были выполнены. У них есть __mro__атрибут, который показывает порядок поиска.

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

Новые объекты класса стиля не могут быть вызваны, если не получены из Exception

В Python 2.5 можно было создать много классов, в Python 2.6 это было удалено. На Python 2.7.3:

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False
Автор: Ciro Santilli 新疆改造中心法轮功六四事件 Размещён: 13.11.2013 09:36
Вопросы из категории :
32x32