Kelas python mewarisi objek

1245

Apakah ada alasan untuk mewarisi suatu deklarasi kelas object?

Saya baru saja menemukan beberapa kode yang melakukan ini dan saya tidak dapat menemukan alasan yang bagus mengapa.

class MyClass(object):
    # class code follows...
tjvr
sumber
2
Ini menciptakan kelas gaya baru .
SLaks
116
Jawaban untuk pertanyaan ini (sementara sederhana) cukup sulit ditemukan. Googling hal-hal seperti "kelas dasar objek python" atau serupa muncul dengan halaman dan halaman tutorial tentang pemrograman berorientasi objek. Mengalami peningkatan karena ini adalah tautan pertama yang mengarahkan saya ke istilah pencarian "objek python gaya lama vs baru"
extremelylyuperiorman

Jawaban:

765

Apakah ada alasan untuk mewarisi suatu deklarasi kelas object?

Dalam Python 3, terlepas dari kompatibilitas antara Python 2 dan 3, tidak ada alasan . Dalam Python 2, banyak alasan .


Cerita Python 2.x:

Dalam Python 2.x (dari 2.2 dan seterusnya) ada dua gaya kelas tergantung pada ada atau tidaknya objectsebagai kelas dasar:

  1. kelas gaya "klasik" : mereka tidak memiliki objectsebagai kelas dasar:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. kelas gaya "baru" : mereka memiliki, secara langsung atau tidak langsung (misalnya mewarisi dari tipe bawaan ), objectsebagai kelas dasar:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)
    

Tanpa ragu, ketika menulis sebuah kelas, Anda selalu ingin mengikuti kelas gaya baru. Manfaat melakukan banyak, untuk daftar beberapa di antaranya:

  • Dukungan untuk deskriptor . Secara khusus, konstruksi berikut ini dimungkinkan dengan deskriptor:

    1. classmethod: Metode yang menerima kelas sebagai argumen implisit, bukan contoh.
    2. staticmethod: Metode yang tidak menerima argumen implisit selfsebagai argumen pertama.
    3. properti dengan property: Membuat fungsi untuk mengelola mendapatkan, menetapkan, dan menghapus atribut.
    4. __slots__: Menghemat konsumsi memori kelas dan juga menghasilkan akses atribut yang lebih cepat. Tentu saja, itu memberlakukan batasan .
  • The __new__metode statis: memungkinkan Anda menyesuaikan bagaimana baru contoh kelas dibuat.

  • Metode resolusi urutan (MRO) : dalam urutan apa kelas dasar suatu kelas akan dicari ketika mencoba menyelesaikan metode mana yang akan dipanggil.

  • Terkait dengan MRO, superpanggilan . Lihat juga, super()dianggap super.

Jika Anda tidak mewarisi object, lupakan ini. Deskripsi yang lebih lengkap tentang poin-poin sebelumnya bersama dengan fasilitas kelas gaya "baru" lainnya dapat ditemukan di sini .

Salah satu kelemahan dari kelas gaya baru adalah bahwa kelas itu sendiri lebih menuntut banyak memori. Namun, kecuali jika Anda membuat banyak objek kelas, saya ragu ini akan menjadi masalah dan itu adalah tenggelam negatif di lautan positif.


Cerita Python 3.x:

Dalam Python 3, semuanya disederhanakan. Hanya kelas gaya baru yang ada (disebut sebagai kelas), jadi, satu-satunya perbedaan dalam penambahan objectadalah Anda harus mengetikkan 8 karakter lagi. Ini:

class ClassicSpam:
    pass

benar-benar setara (terlepas dari nama mereka :-) dengan ini:

class NewSpam(object):
     pass

dan untuk ini:

class Spam():
    pass

Semua ada objectdi mereka __bases__.

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

Jadi, apa yang harus kamu lakukan?

Dalam Python 2: selalu mewarisi dari objectsecara eksplisit . Dapatkan fasilitasnya.

Dalam Python 3: mewarisi dari objectjika Anda menulis kode yang mencoba menjadi Python agnostik, yaitu, ia harus bekerja baik dalam Python 2 dan Python 3. Jika tidak, itu tidak ada bedanya karena Python menyisipkannya untuk Anda di balik layar.

Dimitris Fasarakis Hilliard
sumber
"tergantung pada ada atau tidaknya tipe bawaan sebagai kelas dasar" => sebenarnya ini bukan tentang "tidak ada atau ada tipe builtin sebagai kelas dasar" tetapi apakah kelas tersebut mewarisi - langsung atau tidak langsung - dari object. IIRC ada titik waktu di mana tidak semua tipe builtin di mana porting ke kelas gaya baru
bruno desthuilliers
@brunodesthuilliers Kesan saya adalah bahwa semua tipe bawaan memang mewarisi dari object. Saya memiliki Python 2.2.3 di sekitar dan setelah pemeriksaan cepat saya tidak dapat menemukan pelaku tetapi, saya akan menulis ulang jawabannya nanti untuk membuatnya lebih jelas. Akan tertarik jika Anda dapat menemukan contoh, keingintahuan saya terguncang.
Dimitris Fasarakis Hilliard
Dalam semua kejujuran (lih "IIRC" dalam komentar saya sebelumnya) saya tidak 101% yakin tentang hal ini (apakah semua tipe bawaan sudah dikonversi ke kelas gaya baru ketika kelas gaya baru diperkenalkan) - Saya mungkin hanya polos salah, atau ini mungkin hanya menyangkut beberapa jenis lib standar (tetapi tidak builtin). Namun saya pikir seharusnya lebih baik untuk menjelaskan bahwa apa yang membuat kelas gaya baru ada objectdi pangkalan itu.
bruno desthuilliers
7
terlalu buruk stackoverflow hanya melakukan upvote = upvote +1 untuk jawaban yang agak ini, berharap saya bisa melakukan upvote + = N
PirateApp
1
staticmethoddan classmethodbekerja dengan baik bahkan di kelas gaya lama. propertysorta berfungsi untuk membaca di kelas gaya lama, itu hanya gagal untuk mencegat menulis (jadi jika Anda menetapkan nama, instance mendapatkan atribut dari nama yang diberikan yang membayangi properti). Perhatikan juga bahwa __slots__peningkatan kecepatan akses atribut sebagian besar adalah tentang kehilangan kerugian yang diakibatkan oleh akses atribut kelas-gaya baru, jadi itu bukan nilai jual kelas-kelas gaya baru (penghematan memori adalah nilai jual).
ShadowRanger
540

Python 3

  • class MyClass(object): = Kelas gaya baru
  • class MyClass:= Kelas gaya baru (secara implisit diturunkan dari object)

Python 2

  • class MyClass(object): = Kelas gaya baru
  • class MyClass:= KELAS GAYA TUA

Penjelasan :

Saat mendefinisikan kelas dasar dalam Python 3.x, Anda diizinkan untuk menghapus objectdari definisi. Namun, ini dapat membuka pintu bagi masalah yang sangat sulit dilacak ...

Python memperkenalkan kelas gaya baru kembali di Python 2.2, dan sekarang kelas gaya lama benar-benar sangat tua. Diskusi kelas gaya lama dimakamkan di dokumen 2.x , dan tidak ada di dokumen 3.x.

Masalahnya adalah, sintaks untuk kelas gaya lama dengan Python 2.x adalah sama dengan sintaks alternatif untuk kelas gaya baru di Python 3.x . Python 2.x masih sangat banyak digunakan (misalnya GAE, Web2Py), dan kode apa pun (atau pembuat kode) tanpa disadari membawa definisi kelas gaya 3.x ke dalam kode 2.x akan berakhir dengan beberapa objek dasar yang sudah usang. Dan karena kelas gaya lama tidak ada di radar siapa pun, mereka kemungkinan tidak akan tahu apa yang menimpa mereka.

Jadi cukup jelaskan dan hemat beberapa pengembang 2.x.

Yarin
sumber
13
"Ketika mendefinisikan kelas dasar dalam Python 3.x, Anda diizinkan untuk menjatuhkan objek dari definisi. Namun, ini dapat membuka pintu untuk masalah yang sangat sulit dilacak ..." Masalah apa yang Anda maksud?
Aidis
6
@Aidis: Saya pikir maksud mereka adalah kode yang berjalan pada Py2 dan Py3 akan baik-baik saja pada Py3, tetapi rusak pada Py2 jika itu bergantung pada fitur-fitur kelas gaya baru. Secara pribadi, jika saya menulis kode seperti itu, saya menghilangkan warisan eksplisit dan hanya meletakkan __metaclass__ = typedi bagian atas modul (setelah from __future__ import absolute_import, division, print_functionbaris :-)); itu adalah peretas kompatibilitas di Py2 yang membuat semua kelas yang kemudian didefinisikan dalam modul gaya baru secara default, dan di Py3, itu benar-benar diabaikan (hanya variabel global acak yang ada di sekitar), jadi tidak berbahaya.
ShadowRanger
400

Ya, ini adalah objek 'gaya baru'. Itu adalah fitur yang diperkenalkan di python2.2.

Objek gaya baru memiliki model objek yang berbeda dengan objek klasik, dan beberapa hal tidak akan berfungsi dengan baik dengan objek gaya lama, misalnya super(), @propertydan deskriptor. Lihat artikel ini untuk deskripsi yang baik tentang apa kelas gaya baru itu.

Tautan SO untuk deskripsi perbedaan: Apa perbedaan antara gaya lama dan kelas gaya baru di Python?

Jerub
sumber
110
Beri ini +1. Perhatikan bahwa kelas gaya lama hilang dengan Python 3, jadi Anda hanya perlu mewarisi dari objectdalam Python 2.
9
Ini bukan jawaban yang nyata. Saya hanya memberikan referensi ke artikel lain. Saya pikir jawaban Yarin harus diterima sebagai jawaban untuk pertanyaan ini.
alwbtc
2
@alwbtc: Jawaban ini juga memiliki sesuatu yang baru. Misalnya menyebutkan "super ()" membawa saya ke yang penting [di sini] ( stackoverflow.com/questions/576169/… ).
ViFI
34

Sejarah dari Learn Python the Hard Way :

Versi asli Python tentang suatu kelas telah rusak dalam banyak hal serius. Pada saat kesalahan ini dikenali itu sudah terlambat, dan mereka harus mendukungnya. Untuk memperbaiki masalah, mereka membutuhkan beberapa gaya "kelas baru" sehingga "kelas lama" akan tetap berfungsi tetapi Anda dapat menggunakan versi baru yang lebih benar.

Mereka memutuskan bahwa mereka akan menggunakan kata "objek", huruf kecil, untuk menjadi "kelas" yang Anda warisi untuk membuat kelas. Ini membingungkan, tetapi sebuah kelas mewarisi dari kelas yang bernama "objek" untuk membuat kelas tetapi itu bukan objek yang benar-benar kelasnya, tetapi jangan lupa untuk mewarisi dari objek.

Juga hanya untuk memberi tahu Anda apa perbedaan antara kelas gaya baru dan kelas gaya lama, kelas gaya baru selalu mewarisi dari objectkelas atau dari kelas lain yang diwarisi dari object:

class NewStyle(object):
    pass

Contoh lain adalah:

class AnotherExampleOfNewStyle(NewStyle):
    pass

Sementara kelas dasar gaya lama terlihat seperti ini:

class OldStyle():
    pass

Dan kelas anak gaya lama terlihat seperti ini:

class OldStyleSubclass(OldStyle):
    pass

Anda dapat melihat bahwa kelas dasar Gaya Lama tidak mewarisi dari kelas lain, namun, kelas Gaya Lama tentu saja dapat mewarisi dari satu sama lain. Mewarisi dari objek menjamin bahwa fungsionalitas tertentu tersedia di setiap kelas Python. Kelas gaya baru diperkenalkan dengan Python 2.2

disp_name
sumber
8
Memanggil kelas root objecttidak terlalu membingungkan, dan sebenarnya itu cukup standar. Smalltalk memiliki kelas root bernama Object, dan root metaclass bernama Class. Mengapa? Karena, seperti Dogkelas untuk anjing, Objectkelas untuk objek, dan Classkelas untuk kelas. Java, C #, ObjC, Ruby, dan sebagian besar bahasa OO berbasis kelas lainnya yang digunakan orang saat ini yang memiliki kelas root menggunakan beberapa variasi Objectseperti namanya, bukan hanya Python.
abarnert
30

Ya, ini bersejarah . Tanpanya, itu menciptakan kelas gaya lama.

Jika Anda menggunakan type()objek gaya lama, Anda hanya mendapatkan "instance". Pada objek gaya baru Anda mendapatkan kelasnya.

rajutan
sumber
Juga, jika Anda menggunakan type()kelas gaya lama, Anda mendapatkan "classobj" bukannya "ketik".
Joel Sjögren
7

Sintaks pernyataan penciptaan kelas:

class <ClassName>(superclass):
    #code follows

Dengan tidak adanya superclasses lain yang ingin Anda warisi secara khusus, superclassseharusnya selalu demikian object, yang merupakan akar dari semua kelas dengan Python.

objectsecara teknis akar dari "gaya baru" kelas di Python. Tetapi kelas-kelas gaya baru hari ini sama baiknya dengan menjadi satu-satunya gaya kelas.

Tapi, jika Anda tidak secara eksplisit menggunakan kata objectsaat membuat kelas, maka seperti yang disebutkan lainnya, Python 3.x secara implisit mewarisi dari objectsuperclass. Tapi saya kira eksplisit selalu lebih baik daripada implisit (neraka)

Referensi

kmario23
sumber