Nilai yang dikembalikan oleh kelas Python

Saya mencoba membuat kelas yang mengembalikan nilai, bukan diri sendiri.

Saya akan menunjukkan contoh perbandingan dengan sebuah daftar:

>>> l = list()
>>> print(l)
[]
>>> class MyClass:
>>>     pass

>>> mc = MyClass()
>>> print mc
<__main__.MyClass instance at 0x02892508>

Saya perlu MyClass mengembalikan sebuah daftar, seperti yang dilakukan list(), bukan info instance. Saya tahu bahwa saya bisa membuat subclass dari list. Tetapi apakah ada cara untuk melakukannya tanpa subclassing?

Saya ingin meniru sebuah daftar (atau objek lain):

>>> l1 = list()
>>> l2 = list()
>>> l1
[]
>>> l2
[]
>>> l1 == l2
True
>>> class MyClass():
def __repr__(self):
    return '[]'

>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1
[]
>>> m2
[]
>>> m1 == m2
False

Mengapa m1 == m2 Salah? Ini pertanyaannya.

Saya minta maaf jika saya tidak menanggapi Anda semua. Saya mencoba semua solusi yang anda berikan kepada saya. Saya tidak bisa menggunakan def, karena saya perlu menggunakan fungsi-fungsi seperti setitem, getitem, dll.

Saya pikir Anda sangat bingung tentang apa yang sedang terjadi.

Dalam Python, semuanya adalah objek:

  • [] (sebuah daftar) adalah sebuah objek
  • 'abcde' (sebuah string) adalah sebuah objek
  • 1 (sebuah bilangan bulat) adalah sebuah objek
  • MyClass() (sebuah instance) adalah sebuah objek
  • MyClass (sebuah kelas) juga merupakan sebuah objek
  • Daftar (sebuah tipe - seperti kelas) juga merupakan sebuah objek

Semuanya adalah "values" dalam artian bahwa mereka adalah suatu hal dan bukan nama yang merujuk pada suatu hal. (Variabel adalah nama yang merujuk pada nilai.) Nilai bukanlah sesuatu yang berbeda dari objek dalam Python.

Ketika Anda memanggil objek kelas (seperti MyClass() atau list()), ia akan mengembalikan instance dari kelas tersebut. (list sebenarnya adalah sebuah tipe dan bukan kelas, tapi saya sedikit menyederhanakan di sini).

Ketika Anda print sebuah objek (yaitu mendapatkan representasi string dari sebuah objek), objek itu __str__ atau __repr__ metode ajaib dipanggil dan nilai yang dikembalikan dicetak.

Sebagai contoh:

>>> class MyClass(object):
...     def __str__(self):
...             return "MyClass([])"
...     def __repr__(self):
...             return "I am an instance of MyClass at address "+hex(id(self))
... 
>>> m = MyClass()
>>> print m
MyClass([])
>>> m
I am an instance of MyClass at address 0x108ed5a10
>>> 

Jadi apa yang Anda minta, "Saya perlu MyClass mengembalikan sebuah daftar, seperti list(), bukan info instance," tidak masuk akal. list() mengembalikan sebuah instance daftar. MyClass() mengembalikan instance MyClass. Jika Anda menginginkan instance daftar, dapatkan saja instance daftar. Jika masalahnya adalah bagaimana objek-objek ini terlihat ketika Anda mencetak atau melihatnya di konsol, maka buatlah metode __str__ dan __repr__ yang merepresentasikannya seperti yang Anda inginkan untuk direpresentasikan.

Update untuk pertanyaan baru tentang kesetaraan

Sekali lagi, __str__ dan __repr__ hanya untuk printing, dan tidak mempengaruhi objek dengan cara lain. Hanya karena dua objek memiliki nilai __repr__ yang sama tidak berarti mereka sama!

MyClass() != MyClass() karena kelas Anda tidak mendefinisikan bagaimana ini akan sama, sehingga kembali ke perilaku default (dari tipe objek), yaitu bahwa objek hanya sama dengan dirinya sendiri:

>>> m = MyClass()
>>> m1 = m
>>> m2 = m
>>> m1 == m2
True
>>> m3 = MyClass()
>>> m1 == m3
False

Jika Anda ingin mengubahnya, gunakan salah satu metode ajaib perbandingan

Sebagai contoh, Anda bisa memiliki objek yang sama dengan segalanya:

>>> class MyClass(object):
...     def __eq__(self, other):
...             return True
... 
>>> m1 = MyClass()
>>> m2 = MyClass()
>>> m1 == m2
True
>>> m1 == m1
True
>>> m1 == 1
True
>>> m1 == None
True
>>> m1 == []
True

Saya pikir Anda harus melakukan dua hal:

  1. Lihatlah panduan penggunaan metode ajaib di Python.

  2. Justifikasi mengapa Anda tidak melakukan subclassing list jika apa yang Anda inginkan sangat mirip list. Jika subclassing tidak sesuai, Anda dapat mendelegasikan ke instance list yang dibungkus sebagai gantinya:

     class MyClass(objek):
         def __init__(self):
             self._list = []
         def __getattr__(self, name):
             return getattr(self._list, nama)
    
         # metode __repr__ dan __str__ secara otomatis dibuat
         # untuk setiap kelas, jadi jika kita ingin mendelegasikannya kita harus
         # melakukannya secara eksplisit
         def __repr__(self):
             return "MyClass(%s)" % repr(self._list)
         def __str__(self):
             return "MyClass(%s)" % str(self._list)

    Ini sekarang akan bertindak seperti daftar tanpa menjadi daftar (yaitu, tanpa subclassing daftar).

     >>>> c = MyClass()
     >>> c.append(1)
     >>> c
     MyClass([1])
Komentar (3)
Larutan

Jika yang Anda inginkan adalah cara untuk mengubah kelas Anda menjadi semacam daftar tanpa mensubclassing daftar, maka buatlah sebuah method yang mengembalikan sebuah daftar:

def MyClass():
    def __init__(self):
        self.value1 = 1
        self.value2 = 2

    def get_list(self):
        return [self.value1, self.value2...]

>>>print MyClass().get_list()
[1, 2...]

Jika yang Anda maksudkan adalah bahwa print MyClass() akan mencetak sebuah daftar, override saja __repr__:

class MyClass():        
    def __init__(self):
        self.value1 = 1
        self.value2 = 2

    def __repr__(self):
        return repr([self.value1, self.value2])

EDIT: Saya lihat maksud Anda adalah bagaimana membuat objek membandingkan. Untuk itu, Anda menimpa metode __cmp__.

class MyClass():
    def __cmp__(self, other):
        return cmp(self.get_list(), other.get_list())
Komentar (3)

Anda sedang mendeskripsikan sebuah fungsi, bukan kelas.

def Myclass():
    return []
Komentar (3)