Koja je razlika između starog stila i novih klasa stila u Pythonu?

Koja je razlika između starog stila i novih klasa stila u Pythonu? Postoji li razlog za korištenje starih klasa ovih dana?

861
10 сент. Samo za čitanje postavljeno 10. rujna. 2008-09-10 21:01 '08 u 21:01 2008-09-10 21:01
@ 9 odgovora

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

Prije Pythona 2.1, korišteni su samo stari stilski stilovi.

Koncept (staromodne) klase nije povezan s konceptom tipa: ako je x instanca klase starog stila, onda x.__class__ označava klasu x , ali type(x) uvijek <type 'instance'> .

To odražava činjenicu da su svi primjeri starog stila, bez obzira na klasu, implementirani pomoću jednog ugrađenog tipa, nazvanog instanca.

Klase novog stila uvedene su u Python 2.2 kako bi se unificirali pojmovi klase i tipa . Nova klasa stila je samo korisnički definirani tip, ne više, ni manje.

Ako je x instanca nove klase stila, tada type(x) obično odgovara x.__class__ (iako to nije zajamčeno - instanca klase novog stila dopuštena je da poništi vrijednost vraćenu za x.__class__ )

Glavna motivacija za uvođenje klase novog stila jest pružanje jedinstvenog objektnog modela s potpunim metamodelom .

Ona također ima brojne neposredne koristi, kao što je mogućnost podklasa većine ugrađenih vrsta ili uvođenje "deskriptora" koji omogućuju izračunavanje svojstava.

Zbog razloga kompatibilnosti, razredi su i dalje isti .

Klase novog stila kreiraju se određivanjem druge klase novog stila (tipa) kao nadređene klase ili objekta "najviše razine", ako nije potreban nijedan drugi roditelj.

Ponašanje klasa novog stila razlikuje se od ponašanja klasa starog stila u nizu važnih detalja, pored onoga što se vraća.

Neke od tih promjena su fundamentalne za novi objektni model, na primjer, kada pozivate posebne metode. Drugi su "popravci" koji se ranije nisu mogli implementirati za probleme kompatibilnosti, kao što je redoslijed rješavanja metoda u slučaju višestrukog nasljeđivanja.

Python 3 ima samo nove klase stila .

Bez obzira jeste li podklasa object ili ne, klasa je nova za Python 3.

489
10 сент. Odgovor dao je Mark Cidade 10. rujna 2008-09-10 21:02 '08 u 21:02 2008-09-10 21:02

Izjava tiče:

Klase novog stila nasljeđuju se od objekta ili iz drugog razreda novog stila.

 class NewStyleClass(object): pass class AnotherNewStyleClass(NewStyleClass): pass 

U klasama starog stila nije.

 class OldStyleClass(): pass 
283
30 июля '09 в 4:21 2009-07-30 04:21 odgovor dao Mark Harrison 30. srpnja '09 u 4:21 2009-07-30 04:21

Važne promjene u ponašanju između starih i novih klasa stila

  • super dodano
  • MRO je promijenjen (objašnjeno u nastavku)
  • dodani deskriptori
  • objekti klase novog stila ne mogu se povisiti ako nisu izvedeni iz Exception (primjer niže)
  • __slots__ dodao / la

MRO (redoslijed naloga) je promijenjen

Ovo je spomenuto u drugim odgovorima, ali ovdje je specifičan primjer razlike između klasičnih MRO i C3 MRO (korištenih u novim klasama stila).

Pitanje je redoslijed u kojem se atributi (uključujući metode i varijable članova) traže u višestrukom nasljeđivanju.

Klasične klase obavljaju dubinsko pretraživanje s lijeva na desno. Zaustavite se u prvoj utakmici. Oni nemaju atribut __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 

Klase novog MRO stila je teže sintetizirati u jednoj engleskoj rečenici. Ovdje je detaljno objašnjeno. Jedno od njegovih svojstava je da se osnovna klasa gleda tek nakon što su izvedene sve izvedene klase. Oni imaju atribut __mro__ , koji prikazuje redoslijed pretraživanja.

 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) 

Objekti klase novog stila ne mogu se podići ako nisu dobiveni iz Exception

Oko Pythona 2.5 mogu se podići mnoge klase, dok je Python 2.6 uklonjen. U Pythonu 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
13 нояб. Odgovor koji je dao Ciro Santilli 13 改造 中心 六四 事件 法轮功 13. studenog 2013-11-13 12:36 '13 u 12:36 2013-11-13 12:36

Klase starog stila još su malo brže za traženje atributa. To obično nije važno, ali može biti korisno za Python 2.x kod visokih performansi:

 U [3]: klasa A:...: def __init __ (self):...: self.a = 'hi there'...:  U [4]: ​​klasa B (objekt):...: def __init __ (self):...: self.a = 'hi there'...:  U [6]: aobj = A () U [7]: bobj = B () U [8]:% timeit aobj.a 10.000.000 petlji, najbolje od 3: 78.7 ns po petlji U [10]:% timeit bobj.a 10.000.000 petlji, najbolje od 3: 86.9 ns po petlji
35
12 июля '10 в 14:26 2010-07-12 14:26 odgovor je dat xioxox 12. srpnja '10 u 14:26 2010-07-12 14:26

Guido je napisao Inside Story na New-Style klasama , stvarno odličan članak o novom stilu i klasi starog stila u Pythonu.

Python 3 ima samo klasu novog stila, čak i ako napišete "klasu starog stila", ona je implicitno izvedena iz object .

U klasama novog stila postoje neke dodatne značajke koje nedostaju u klasama starog stila, na primjer, super i novi C3 mro , neke magijske metode, itd.

30
24 апр. odgovor dao Xiao Hanyu 24. travnja 2013-04-24 16:41 '13 u 16:41 2013-04-24 16:41

Ovdje je vrlo praktična, istinita / lažna razlika. Jedina razlika između dviju verzija sljedećeg koda je da u drugoj verziji, osoba nasljeđuje objekt. Osim toga, dvije verzije su identične, ali imaju različite rezultate:

1) stare klase stila

 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) klase novog stila

 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
09 окт. odgovor je dat ychaouche 09 okt. 2013-10-09 16:40 '13 u 16:40 2013-10-09 16:40

Klase novog stila nasljeđuju od object i moraju biti napisane kao takve u Pythonu 2.2 i dalje (tj. class Classname(object): umjesto class Classname: . Glavna promjena je ujedinjenje tipova i klasa, a dobra sporedna posljedica toga je da vam omogućuje da naslijedite od ugrađenih tipova.

Pročitajte više.

7
28 окт. odgovor je dat Halo 28. listopada. 2008-10-28 12:54 '08 u 12:54 2008-10-28 12:54

Nove klase stila mogu koristiti super(Foo, self) , gdje je Foo klasa i self je instanca.

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

Vraća proxy objekt koji delegira pozive metoda roditeljskoj ili izvornoj klasi tipa. Ovo je korisno za pristup naslijeđenim metodama koje su nadjačane u klasi. Redoslijed pretraživanja je isti kao i za getattr (), osim što je sam tip preskočen.

A u Pythonu 3.x, možete jednostavno koristiti super() unutar klase bez parametara.

4
30 апр. odgovor je dao jamylak 30 Apr 2013-04-30 11:28 '13 u 11:28 2013-04-30 11:28

Umjesto toga, uvijek trebate koristiti klase novog stila ako nemate kod koji bi trebao raditi s verzijama Pythona starijim od 2.2.

3
11 сент. Odgovor dao Tony Meyer 11. rujna 2008-09-11 00:23 '08 u 0:23 2008-09-11 00:23

Pogledajte i ostala pitanja o ili o Postavi pitanje