Haruskah semua kelas Python memperluas objek?

129

Saya telah menemukan bahwa kedua pekerjaan berikut:

class Foo():
    def a(self):
        print "hello"

class Foo(object):
    def a(self):
        print "hello"

Haruskah semua kelas Python memperluas objek? Apakah ada masalah potensial dengan tidak memperluas objek?

Kara
sumber
2
Apakah ada perbedaan antara class Foo():dan class Foo:? Seperti yang saya amati, keduanya bekerja dalam Python 3.
Wolf
Itu dijawab dengan baik dalam pertanyaan ini: stackoverflow.com/questions/4015417/…
nngeek

Jawaban:

117

Dalam Python 2, tidak mewarisi dari objectakan membuat kelas gaya lama, yang, di antara efek lainnya, menyebabkan typememberikan hasil yang berbeda:

>>> class Foo: pass
... 
>>> type(Foo())
<type 'instance'>

vs.

>>> class Bar(object): pass
... 
>>> type(Bar())
<class '__main__.Bar'>

Juga aturan untuk pewarisan berganda berbeda dalam hal yang saya bahkan tidak akan mencoba untuk meringkasnya di sini. Semua dokumentasi bagus yang pernah saya lihat tentang MI menjelaskan kelas gaya baru.

Akhirnya, kelas gaya lama telah menghilang dalam Python 3, dan pewarisan dari objectmenjadi tersirat. Jadi, selalu lebih suka kelas-kelas gaya baru kecuali jika Anda perlu compat mundur dengan perangkat lunak lama.

Fred Foo
sumber
68

Dalam Python 3, kelas diperluas objectsecara implisit, apakah Anda mengatakannya sendiri atau tidak.

Di Python 2, ada kelas gaya lama dan gaya baru . Untuk memberi sinyal suatu kelas adalah gaya baru, Anda harus mewarisi secara eksplisit dari object. Jika tidak, implementasi gaya lama digunakan.

Anda biasanya menginginkan kelas gaya baru. Mewarisi dari objectsecara eksplisit. Perhatikan bahwa ini juga berlaku untuk kode Python 3 yang bertujuan agar kompatibel dengan Python 2.

slezica
sumber
Ya, perbedaan yang ditunjukkan Free Foo , telah hilang, BTW: apakah tanda kurung kosong opsional?
Wolf
4
Ada banyak kode python 3 yang menggunakan foo (objek) :. Apakah ini hanya sebuah konvensi?
RFV5
2
@RFVenter Ini mungkin kode yang seharusnya dijalankan di bawah kedua Python 2 dan 3, dalam hal ini Anda perlu untuk subclass objek secara eksplisit untuk membuat kelas berperilaku sebagian besar sama di bawah Python 2.
blubberdiblub
@blubberdiblub Itulah yang saya duga TETAPI proyek kami berjalan secara eksklusif pada python 3.5 virtualenv. Saya pikir kode tersebut harus sudah disalin dari proyek python 2.
RFV5
@RFVenter yup, itu mungkin penjelasan lain. Dan tentu saja, jika itu hanya Python 3.x saja sekarang, tidak masalah untuk menyingkirkan referensi objek.
blubberdiblub
17

Dalam python 3 Anda dapat membuat kelas dalam tiga cara berbeda & secara internal mereka semua sama (lihat contoh). Tidak masalah bagaimana Anda membuat kelas, semua kelas di python 3 mewarisi dari objek khusus yang disebut objek . Objek kelas adalah kelas mendasar dalam python dan menyediakan banyak fungsi seperti metode double-underscore, deskriptor, metode super (), metode properti () dll.

Contoh 1.

class MyClass:
 pass

Contoh 2.

class MyClass():
 pass

Contoh 3.

class MyClass(object):
  pass
N Randhawa
sumber
1
Ini tidak sepenuhnya benar ... stackoverflow.com/questions/1238606/…
Philip Adler
Saya tidak yakin saya mengikuti Anda. Dan ya, mungkin tidak relevan bagi kebanyakan orang hingga relevan.
Philip Adler
@ PhilipAdler Biasanya diasumsikan yang objectmembuat referensi ke built-in object. Jika kita harus memperhitungkan bahwa pengenal bawaan CPython apa pun dapat diganti, kita hampir tidak dapat membuat beberapa pernyataan tentang model data. Bisakah itu diperdebatkan dengan serius yang strtidak selalu menerima string sebagai argumen karena orang dapat menetapkan builtins.str = None?
Nuno André
Saya terus melihat klaim ini bahwa ini "secara luas dianggap", dan saya menerima bahwa itu adalah asumsi bahwa setiap implementasi saat ini membuat (itu bukan persyaratan bahasa), belum pengalaman saya bahwa mayoritas programmer python saya telah bertemu berasumsi ini, mengetahuinya, atau bahkan telah mempertimbangkannya. Terlepas dari itu, pernyataan bahwa itu umumnya diasumsikan, bahkan jika benar, tidak membuat pernyataan saya tidak benar bahwa kesetaraan itu tidak sepenuhnya benar.
Philip Adler
1

Ya, semua kelas Python harus memperluas (atau lebih tepatnya subkelas, ini Python di sini) objek. Walaupun biasanya tidak ada masalah serius yang akan terjadi, dalam beberapa kasus (seperti dengan banyak pohon warisan) ini akan menjadi penting. Ini juga memastikan kompatibilitas yang lebih baik dengan Python 3.

pydsigner
sumber
1
tepatnya, secara teknis jika Anda tidak, Anda akan mendapatkan kelas klasik, tetapi tidak ada keuntungan nyata untuk ini dan itu tidak didukung oleh python 3 pula
maks k.
Saya ingin tahu mengapa ini meningkatkan kompatibilitas dengan python3. Untuk pemahaman saya, python3 akan membuatnya memperluas objek secara otomatis bahkan jika Anda tidak menentukannya, kan?
Paul Lo
2
@ PaulLo Benar, tetapi jika Anda secara eksplisit mewarisi dari objek, Anda akan mendapatkan perilaku (gaya-baru) yang sama di kedua Python 2 dan Python 3. Ini bukan masalah mengubah cara kerja Python 3, itu masalah menggunakan maju -Kompatibilitas pada Python 2.
pydsigner
Saran ini terlihat tidak terlalu elegan, tetapi jika Anda menangani Python2 dan Python3, tampaknya efektif. Tetapi seberapa relevankah itu dalam praktik?
Wolf
@ Serigala Tergantung pada apa yang Anda lakukan. Jika Anda memiliki pohon warisan yang kompleks, itu cukup berarti. Jika Anda ingin kelas Anda menjadi deskriptor, Anda harus menggunakan gaya baru. Anda dapat mengikuti tautan dari stackoverflow.com/questions/54867/... jika Anda menginginkan informasi lebih mendalam.
pydsigner
1

Seperti jawaban lain yang telah dibahas, pewarisan Python 3 dari objek adalah implisit. Tetapi mereka tidak menyatakan apa yang harus Anda lakukan dan apa itu konvensi.

Contoh dokumentasi Python 3 semuanya menggunakan gaya berikut yang merupakan konvensi, jadi saya sarankan Anda mengikuti ini untuk kode apa pun di Python 3.

class Foo:
    pass

Sumber: https://docs.python.org/3/tutorial/classes.html#class-objects

Contoh kutipan:

Objek kelas mendukung dua jenis operasi: referensi atribut dan instantiasi.

Referensi atribut menggunakan sintaksis standar yang digunakan untuk semua referensi atribut dengan Python: obj.name. Nama atribut yang valid adalah semua nama yang ada di namespace kelas ketika objek kelas dibuat. Jadi, jika definisi kelas tampak seperti ini:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

Kutipan lain:

Secara umum, variabel instance adalah untuk data unik untuk setiap instance dan variabel kelas adalah untuk atribut dan metode yang dibagikan oleh semua instance kelas:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance
jmoz
sumber
0

di python3 tidak ada perbedaan, tetapi di python2 tidak memperluas objectmemberi Anda kelas gaya lama; Anda ingin menggunakan kelas gaya baru di atas kelas gaya lama.

terima kasih
sumber
2
Jawaban ini masuk akal, tetapi penjawab lain sampai di sana lebih cepat dan / atau lebih detail; jawaban ini tidak menambahkan nilai apa pun ke halaman seperti apa adanya.
Mark Amery