Pertanyaan Apa perbedaan antara gaya lama dan kelas gaya baru dengan Python?


Apa perbedaan antara gaya lama dan kelas gaya baru dengan Python? Apakah ada alasan untuk menggunakan kelas gaya lama belakangan ini?


855
2017-09-10 18:01


asal


Jawaban:


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

Hingga Python 2.1, kelas-gaya lama adalah satu-satunya rasa yang tersedia bagi pengguna. Konsep kelas (gaya lama) tidak terkait dengan konsep tipe: if x adalah contoh dari kelas gaya lama, lalu x.__class__ menunjuk kelas x, tapi type(x) selalu <type 'instance'>. Ini mencerminkan fakta bahwa semua instance gaya lama, terlepas dari kelasnya, diimplementasikan dengan satu tipe bawaan, yang disebut instance.

Kelas-kelas gaya baru diperkenalkan dengan Python 2.2 untuk menyatukan konsep kelas dan tipe. Kelas gaya baru hanyalah tipe yang ditentukan pengguna, tidak lebih, tidak kurang. Jika x adalah instance dari kelas gaya baru, maka type(x) biasanya sama dengan x.__class__ (meskipun ini tidak dijamin - instance kelas gaya baru diizinkan untuk mengganti nilai yang dikembalikan x.__class__).

Motivasi utama untuk memperkenalkan kelas gaya baru adalah untuk menyediakan model objek terpadu dengan meta-model lengkap. Ini juga memiliki sejumlah manfaat langsung, seperti kemampuan untuk jenis subclass paling built-in, atau pengenalan "deskriptor", yang memungkinkan properti dihitung.

Untuk alasan kompatibilitas, kelas masih bergaya lama secara default. Kelas gaya baru dibuat dengan menentukan kelas gaya baru (yaitu tipe) sebagai kelas induk, atau objek "tipe tingkat atas" jika tidak ada orang tua lain yang diperlukan. Perilaku kelas-gaya baru berbeda dari kelas-kelas gaya lama dalam sejumlah rincian penting di samping jenis apa yang kembali. Beberapa perubahan ini sangat mendasar untuk model objek baru, seperti cara metode khusus dipanggil. Lainnya adalah "perbaikan" yang tidak dapat diimplementasikan sebelumnya untuk masalah kompatibilitas, seperti urutan resolusi metode dalam kasus multiple inheritance.

Python 3 hanya memiliki kelas-kelas gaya baru. Tidak masalah jika Anda berasal dari subkelas object atau tidak, kelas adalah gaya baru di Python 3.


487
2017-07-30 01:21



Deklarasi-bijaksana:

Kelas-kelas gaya baru mewarisi dari objek, atau dari kelas gaya baru lainnya.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

Kelas gaya lama tidak.

class OldStyleClass():
    pass

282
2017-11-13 09:36



Perubahan perilaku penting antara kelas gaya lama dan baru

  • super ditambahkan
  • MRO berubah (dijelaskan di bawah)
  • deskriptor ditambahkan
  • objek kelas gaya baru tidak dapat ditingkatkan kecuali berasal dari Exception (contoh di bawah)
  • __slots__ ditambahkan

MRO (Method Resolution Order) diubah

Itu disebutkan dalam jawaban lain, tapi di sini ada contoh konkret dari perbedaan antara MRO klasik dan C3 MRO (digunakan dalam kelas gaya baru).

Pertanyaannya adalah urutan di mana atribut (yang termasuk metode dan variabel anggota) dicari dalam multiple inheritance.

Kelas klasiklakukan pencarian mendalam pertama dari kiri ke kanan. Berhenti pada pertandingan pertama. Mereka tidak memiliki __mro__ atribut.

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

Kelas gaya baru MRO lebih rumit untuk disintesis dalam satu kalimat bahasa Inggris. Itu dijelaskan secara rinci sini. Salah satu propertinya adalah bahwa kelas Base hanya dicari setelah semua kelas turunannya telah. Mereka memiliki __mro__ atribut yang menunjukkan urutan pencarian.

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)

Objek kelas gaya baru tidak dapat ditingkatkan kecuali berasal dari Exception

Sekitar Python 2.5 banyak kelas dapat ditingkatkan, sekitar Python 2.6 ini telah dihapus. Pada 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
2017-07-12 11:26



Kelas gaya lama masih sedikit lebih cepat untuk pencarian atribut. Ini biasanya tidak penting, tetapi mungkin berguna dalam kode Python 2.x yang peka terhadap kinerja:

Di [3]: kelas A:
   ...: def __init __ (diri):
   ...: self.a = 'hi there'
   ...:

Di [4]: ​​kelas B (objek):
   ...: def __init __ (diri):
   ...: self.a = 'hi there'
   ...:

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

Dalam [8]:% timeit aobj.a
10000000 loop, terbaik 3: 78,7 ns per loop

Dalam [10]:% timeit bobj.a
10000000 loop, terbaik 3: 86.9 ns per loop

34
2018-04-24 13:41



Guido telah menulis Kisah Dalam tentang Kelas-Kelas Gaya Baru, artikel yang sangat bagus tentang kelas gaya baru dan lama di Python.

Python 3 hanya memiliki kelas gaya baru, bahkan jika Anda menulis 'kelas gaya lama', itu secara implisit berasal object.

Kelas-kelas gaya baru memiliki beberapa fitur canggih yang kurang dalam kelas-kelas gaya lama, seperti super dan yang baru C3 mro, beberapa metode magis, dll.


30
2017-10-09 13:40



Inilah perbedaan yang sangat praktis, Benar / Salah. Satu-satunya perbedaan antara dua versi kode berikut adalah pada versi kedua Person mewarisi dari objek. Selain itu, kedua versi itu identik, tetapi dengan hasil berbeda:

1) kelas gaya lama

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) kelas gaya baru

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
2017-10-28 09:54



Kelas-kelas gaya baru mewarisi dari object dan harus ditulis seperti itu dengan Python 2.2 dan seterusnya (mis. class Classname(object): dari pada class Classname:). Perubahan inti adalah menyatukan jenis dan kelas, dan efek samping yang bagus dari ini adalah memungkinkan Anda untuk mewarisi dari jenis bawaan.

Baca baca descrintro untuk lebih jelasnya.


7
2018-04-30 08:28