Jaka jest różnica między klasami Starego i nowego stylu w Pythonie?

Jaka jest różnica między klasami Starego i nowego stylu w Pythonie? Czy jest jakiś powód, by w dzisiejszych czasach korzystać z zajęć w starym stylu?

Author: laike9m, 2008-09-10

9 answers

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

Do wersji Python 2.1, klasy w starym stylu były jedynymi dostępnymi dla użytkownika.

Pojęcie klasy (starego stylu) nie ma związku z pojęciem typu: jeśli x jest instancją klasy w starym stylu, to x.__class__ oznacza klasę x, ale {[3] } jest zawsze <type 'instance'>.

Odzwierciedla to fakt, że wszystkie instancje w starym stylu, niezależnie od ich klasy, są realizowane z jednym wbudowanym typem, zwanym przykład.

W Pythonie 2.2 wprowadzono nowe klasy w celu ujednolicenia pojęć class I type . Klasa nowego stylu jest po prostu typem zdefiniowanym przez użytkownika, nie więcej, nie mniej.

Jeśli X jest instancją klasy nowego stylu, to type(x) jest zazwyczaj to samo co x.__class__ (choć nie jest to gwarantowane-a instancja klasy nowego stylu może nadpisać zwracaną wartość na x.__class__).

Główną motywacją do wprowadzenia klas nowego stylu jest dostarczenie zunifikowanego modelu obiektowego z pełnym meta-modelem .

[[9]}ma również szereg natychmiastowych korzyści, takich jak zdolność do podklasa większość typów wbudowanych, czyli wprowadzenie " deskryptorów", które umożliwiają obliczanie właściwości.

Ze względu na kompatybilność, klasy są domyślnie nadal w starym stylu .

Klasy nowego stylu są tworzone przez podanie kolejna klasa w Nowym Stylu (tj. Typ) jako klasa nadrzędna, lub obiekt "Typ najwyższego poziomu", jeśli nie potrzebny jest inny rodzic.

Zachowanie klas nowego stylu różni się od zachowania klas starego stylu klas w wielu ważnych szczegółach oprócz tego, jaki rodzaj zwroty.

Niektóre z tych zmian są fundamentalne dla nowego modelu obiektowego, jak sposób wywoływania specjalnych metod. Inne to "poprawki", które nie mogły być zaimplementowane wcześniej dla problemów związanych z kompatybilnością, takich jak metoda kolejność rozwiązywania w przypadku wielokrotnego dziedziczenia.

Python 3 ma tylko klasy nowego stylu .

Bez względu na to, czy podklasujesz z object, czy nie, klasy są w Nowym Stylu w Pythonie 3.

 493
Author: Projesh Bhoumik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-10 08:10:37

Klasy nowego stylu dziedziczą z obiektu lub z innej klasy nowego stylu.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass
Klasy w starym stylu nie.]}
class OldStyleClass():
    pass
 283
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 22:12:38

Ważne zmiany zachowania pomiędzy klasami Starego i nowego stylu

  • super Dodano
  • MRO zmienione (wyjaśnione poniżej)
  • deskryptory dodane
  • nowe obiekty klasy stylu nie mogą być wywoływane, chyba że pochodzą z Exception (Przykład poniżej)
  • __slots__ Dodano

MRO (Method Resolution Order) changed

Wspomniano o tym w innych odpowiedziach, ale oto konkretny przykład różnicy między klasycznym MRO i C3 MRO (stosowane w klasach nowego stylu).

Pytanie dotyczy kolejności, w jakiej atrybuty (które zawierają metody i zmienne członkowskie) są wyszukiwane w dziedziczeniu wielokrotnym.

Klasy Klasyczne najpierw przeszukują głębię od lewej do prawej. Zatrzymaj się na pierwszym meczu. Nie posiadają atrybutu __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

New-style classes MRO jest bardziej skomplikowane do zsyntetyzowania w jednym angielskim zdaniu. Jest to szczegółowo wyjaśnione tutaj . Jedną z jego właściwości jest to, że klasa bazowa jest wyszukiwana tylko wtedy, gdy wszystkie jej klasy pochodne zostały już znalezione. Mają atrybut __mro__, który pokazuje kolejność wyszukiwania.

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)

Nowe obiekty klasy stylu nie mogą być wywoływane, chyba że pochodzą z Exception

Wokół Pythona 2.5 można było podnieść wiele klas, wokół Pythona 2.6 to zostało usunięte. W Pythonie 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
 197
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:50

Klasy starych stylów są nadal nieznacznie szybsze do wyszukiwania atrybutów. Zazwyczaj nie jest to ważne, ale może być przydatne w Pythonie 2 wrażliwym na wydajność.kod 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
Author: xioxox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-12 11:26:52

Guido napisał The Inside Story on New-Style Classes , naprawdę świetny artykuł o klasach new-style i old-style w Pythonie.

Python 3 ma tylko klasę new-style, nawet jeśli piszesz klasę old-style, jest ona pośrednio pochodna od object.

Klasy nowego stylu mają pewne zaawansowane funkcje, których brakuje w klasach starego stylu, takie jak super i Nowy C3 mro , niektóre magiczne metody itp.

 30
Author: Xiao Hanyu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 19:54:00

Oto bardzo praktyczna, Prawda / Fałsz różnica. Jedyną różnicą między dwiema wersjami poniższego kodu jest to, że w drugiej wersji osoba dziedziczy po obiekcie. Poza tym obie wersje są identyczne, ale z różnymi wynikami:

1) klasy w starym stylu

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) klasy nowego stylu

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>
>>>
 18
Author: ychaouche,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-09 13:40:29

Klasy nowego stylu dziedziczą z object i muszą być zapisane jako takie w Pythonie 2.2 (tj. class Classname(object): zamiast class Classname:). Podstawową zmianą jest ujednolicenie typów i klas, a przyjemnym efektem ubocznym jest to, że pozwala na dziedziczenie z typów wbudowanych.

Przeczytaj descrintro aby uzyskać więcej szczegółów.

 7
Author: Halo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-20 15:09:52

Nowe klasy stylu mogą używać super(Foo, self) gdzie Foo jest klasą, A {[2] } jest instancją.

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

Zwraca obiekt proxy, który deleguje wywołania metody do klasy nadrzędnej lub siostrzanej typu. Jest to przydatne przy dostępie do odziedziczonych metod, które zostały nadpisane w klasie. Kolejność wyszukiwania jest taka sama jak używana przez getattr (), z tym wyjątkiem, że sam typ jest pomijany.

I w Pythonie 3.x możesz po prostu użyć super() wewnątrz klasy bez parametrów.

 4
Author: jamylak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-30 08:28:52

A raczej powinieneś zawsze używać klas nowego stylu, chyba że masz kod, który musi działać z wersjami Pythona starszymi niż 2.2.

 3
Author: Tony Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-10 21:23:53