В чем разница между «class A ()» и «class A (object)»? [Дубликат]

У них есть другое понятное для человека значение.

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

Вы всегда должны указывать, чтобы быть читаемый.

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

859
задан laike9m 5 August 2015 в 10:31
поделиться

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

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

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

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

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

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

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

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

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

488
ответ дан 9 revs, 6 users 56% 28 August 2018 в 02:42
поделиться

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

  • super добавлено
  • 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
195
ответ дан Community 28 August 2018 в 02:42
поделиться

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

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

7
ответ дан Francesco Montesano 28 August 2018 в 02:42
поделиться

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

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

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

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

4
ответ дан jamylak 28 August 2018 в 02:42
поделиться

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

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

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

30
ответ дан Jason Sundram 28 August 2018 в 02:42
поделиться

Декларация:

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

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

В классах старого стиля нет.

class OldStyleClass():
    pass
283
ответ дан Mark Harrison 28 August 2018 в 02:42
поделиться

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

3
ответ дан Tony Meyer 28 August 2018 в 02:42
поделиться

Классы старого стиля все еще немного быстрее для поиска атрибутов. Это обычно не важно, но может быть полезно в высокопроизводительном коде 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
35
ответ дан xioxox 28 August 2018 в 02:42
поделиться

Вот очень практичная, истинная / ложная разница. Единственная разница между двумя версиями следующего кода заключается в том, что во второй версии 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>
>>>
17
ответ дан ychaouche 28 August 2018 в 02:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: