У них есть другое понятное для человека значение.
Однако, в зависимости от оптимизатора запросов, они могут иметь то же значение для машины.
Вы всегда должны указывать, чтобы быть читаемый.
То есть, если это встроенное отношение, используйте явное соединение. если вы согласны с слабо связанными данными, используйте предложение where.
Из 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 имеет только классы нового стиля.
Независимо от того, являетесь ли вы подклассом из
blockquote>object
или нет, классы являются новыми в Python 3.
Важные изменения поведения между старыми и новыми классами стиля
Exception
(пример ниже) __slots__
Добавлено Это было упомянуто в других ответах, но здесь приведен конкретный пример разницы между классическим 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
Классы нового стиля наследуют от object
и должны быть записаны как таковые в Python 2.2 и далее (т. е. class Classname(object):
вместо class Classname:
). Основное изменение заключается в унификации типов и классов, и хороший побочный эффект этого заключается в том, что он позволяет наследовать от встроенных типов.
Прочтите descrintro для получения более подробной информации .
Новые классы стиля могут использовать super(Foo, self)
, где Foo
является классом, а self
является экземпляром.
super(type[, object-or-type])
Возвращает прокси-объект что метод делегатов вызывает класс родительского или родственного класса. Это полезно для доступа к унаследованным методам, которые были переопределены в классе. Порядок поиска аналогичен тому, который используется getattr (), за исключением того, что сам тип пропускается.
blockquote>И в Python 3.x вы можете просто использовать
super()
внутри класса без параметров .
Гвидо написал «Внутренняя история о классах нового стиля» , действительно отличная статья о классе нового стиля и старого стиля в Python.
Python 3 имеет только новые -style class, даже если вы пишете «класс старого стиля», он неявно получен из object
.
В классах нового стиля есть некоторые дополнительные функции, отсутствующие в классах старого стиля, такие как super
и новый C3 mro , некоторые магические методы и т. д.
Декларация:
Классы нового стиля наследуются от объекта или из другого класса нового стиля.
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
В классах старого стиля нет.
class OldStyleClass():
pass
Или, вернее, вы всегда должны использовать классы нового стиля, , если у вас нет кода, который должен работать с версиями Python старше 2.2.
Классы старого стиля все еще немного быстрее для поиска атрибутов. Это обычно не важно, но может быть полезно в высокопроизводительном коде 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
Вот очень практичная, истинная / ложная разница. Единственная разница между двумя версиями следующего кода заключается в том, что во второй версии 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>
>>>