it-swarm-id.com

Apakah ada manfaatnya mendefinisikan kelas di dalam kelas lain dengan Python?

Yang saya bicarakan di sini adalah kelas bersarang. Pada dasarnya, saya memiliki dua kelas yang saya modelkan. Kelas DownloadManager dan kelas DownloadThread. Konsep yang jelas OOP di sini adalah komposisi. Namun, komposisi tidak selalu berarti bersarang, bukan?

Saya memiliki kode yang terlihat seperti ini:

class DownloadThread:
    def foo(self):
        pass

class DownloadManager():
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadThread())

Tapi sekarang saya bertanya-tanya apakah ada situasi di mana bersarang akan lebih baik. Sesuatu seperti:

class DownloadManager():
    class DownloadThread:
        def foo(self):
            pass
    def __init__(self):
        dwld_threads = []
    def create_new_thread():
        dwld_threads.append(DownloadManager.DownloadThread())
90
fuentesjr

Anda mungkin ingin melakukan ini ketika kelas "dalam" adalah satu kali, yang tidak akan pernah digunakan di luar definisi dari kelas luar. Misalnya untuk menggunakan metaclass, kadang-kadang berguna untuk dilakukan

class Foo(object):
    class __metaclass__(type):
        .... 

alih-alih mendefinisikan metaclass secara terpisah, jika Anda hanya menggunakannya sekali.

Satu-satunya waktu saya menggunakan kelas bertingkat seperti itu, saya menggunakan kelas luar hanya sebagai namespace untuk mengelompokkan sekelompok kelas yang terkait erat bersama-sama:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

Kemudian dari modul lain, Anda dapat mengimpor Grup dan merujuk ini sebagai Group.cls1, Group.cls2 dll. Namun orang mungkin berpendapat bahwa Anda dapat mencapai hal yang persis sama (mungkin dengan cara yang kurang membingungkan) dengan menggunakan modul.

108
dF.

Saya tidak tahu Python, tetapi pertanyaan Anda tampaknya sangat umum. Abaikan saya jika ini khusus untuk Python.

Bersarang kelas adalah semua tentang ruang lingkup. Jika Anda berpikir bahwa satu kelas hanya akan masuk akal dalam konteks yang lain, maka yang pertama mungkin adalah kandidat yang baik untuk menjadi kelas bersarang.

Ini adalah pola umum yang menjadikan kelas pembantu sebagai kelas privat dan bersarang.

18
André Chalella

Sebenarnya tidak ada manfaatnya melakukan ini, kecuali jika Anda berurusan dengan metaclasses.

kelas: suite sebenarnya bukan apa yang Anda pikirkan. Ini adalah ruang lingkup yang aneh, dan itu melakukan hal-hal aneh. Itu bahkan tidak membuat kelas! Ini hanya cara mengumpulkan beberapa variabel - nama kelas, basis, kamus atribut, dan metaclass.

Nama, kamus, dan pangkalan semuanya dilewatkan ke fungsi yaitu metaclass, dan kemudian ditugaskan ke variabel 'nama' dalam lingkup di mana kelas: suite itu.

Apa yang bisa Anda peroleh dengan bermain-main dengan metaclasses, dan tentu saja dengan bersarang kelas dalam kelas standar stok Anda, lebih sulit untuk membaca kode, lebih sulit untuk memahami kode, dan kesalahan aneh yang sangat sulit untuk dipahami tanpa menjadi akrab dengan mengapa 'kelas' ruang lingkup sama sekali berbeda dengan yang lain python lingkup.

6
Jerub

Anda bisa menggunakan kelas sebagai generator kelas. Suka (dalam beberapa kode manset :)

class gen(object):
    class base_1(object): pass
    ...
    class base_n(object): pass

    def __init__(self, ...):
        ...
    def mk_cls(self, ..., type):
        '''makes a class based on the type passed in, the current state of
           the class, and the other inputs to the method'''

Saya merasa seperti ketika Anda membutuhkan fungsi ini, itu akan sangat jelas bagi Anda. Jika Anda tidak perlu melakukan sesuatu yang serupa daripada itu mungkin bukan kasus penggunaan yang baik.

5
tim.tadh

Ada penggunaan lain untuk kelas bersarang, ketika seseorang ingin membangun kelas-kelas yang diwariskan yang fungsionalitas yang ditingkatkan dienkapsulasi dalam kelas bersarang tertentu.

Lihat contoh ini:

_class foo:

  class bar:
    ...  # functionalities of a specific sub-feature of foo

  def __init__(self):
    self.a = self.bar()
    ...

  ...  # other features of foo


class foo2(foo):

  class bar(foo.bar):
    ... # enhanced functionalities for this specific feature

  def __init__(self):
    foo.__init__(self)
_

Perhatikan bahwa dalam konstruktor foo, baris self.a = self.bar() akan membangun _foo.bar_ ketika objek yang sedang dibangun sebenarnya adalah objek foo objek, dan _foo2.bar_ objek ketika objek yang sedang dibangun sebenarnya adalah objek _foo2_.

Jika kelas bar didefinisikan di luar kelas foo sebagai gantinya, serta versi warisannya (yang akan disebut _bar2_ misalnya), maka mendefinisikan kelas baru _foo2_ akan jauh lebih menyakitkan, karena konstuktor _foo2_ perlu mengganti baris pertamanya dengan self.a = bar2(), yang menyiratkan penulisan ulang seluruh konstruktor.

4
Thomas

Tidak, komposisi tidak berarti bersarang. Masuk akal untuk memiliki kelas bersarang jika Anda ingin menyembunyikannya lebih banyak di namespace dari kelas luar.

Lagi pula, saya tidak melihat penggunaan praktis untuk bersarang dalam kasus Anda. Ini akan membuat kode lebih sulit untuk dibaca (dipahami) dan juga akan meningkatkan lekukan yang akan membuat garis lebih pendek dan lebih rentan terhadap pemecahan.

1
Cristian Ciupitu