Python __str__ dan daftar

107

Di Java, jika saya memanggil List.toString (), maka secara otomatis akan memanggil metode toString () pada setiap objek di dalam List. Misalnya, jika daftar saya berisi objek o1, ​​o2, dan o3, list.toString () akan terlihat seperti ini:

"[" + o1.toString() + ", " + o2.toString() + ", " + o3.toString() + "]"

Apakah ada cara untuk mendapatkan perilaku serupa dengan Python? Saya menerapkan metode __str __ () di kelas saya, tetapi ketika saya mencetak daftar objek, menggunakan:

print 'my list is %s'%(list)

itu terlihat seperti ini:

[<__main__.cell instance at 0x2a955e95f0>, <__main__.cell instance at 0x2a955e9638>, <__main__.cell instance at 0x2a955e9680>]

bagaimana saya bisa mendapatkan python untuk memanggil __str__ saya secara otomatis untuk setiap elemen di dalam daftar (atau dict dalam hal ini)?

benhsu
sumber

Jawaban:

133

Memanggil string pada daftar python memanggil __repr__metode pada setiap elemen di dalamnya. Untuk beberapa item, __str__dan __repr__sama. Jika Anda menginginkan perilaku itu, lakukan:

def __str__(self):
    ...
def __repr__(self):
    return self.__str__()
David Berger
sumber
7
Mengidentifikasi __str__dengan __repr__biasanya tidak sesuai dengan model data Python , sehingga solusi pemahaman daftar yang diusulkan oleh @ daniel-lew lebih bersifat pythonic.
Ioannis Filippidis
2
Tidak ada argumen. Saya menjawab pertanyaan seperti yang ditanyakan, yang sering kali adalah bagaimana pendatang baru di python ingin memikirkan masalahnya, tetapi itu tidak berarti itulah cara terbaik untuk menjawab.
David Berger
1
Python harus konsisten dengan model datanya sendiri dan melakukan hal yang sama untuk semua primitif dan agregat.
Terrence Brannon
2
Saya pikir perilaku default untuk daftar python salah. Saya berharap bahwa str()pada daftar dikembalikan str()untuk setiap elemen individu di dalamnya.
SuperGeo
21

Anda dapat menggunakan pemahaman daftar untuk menghasilkan daftar baru dengan setiap item str () 'd secara otomatis:

print([str(item) for item in mylist])
Dan Lew
sumber
6
Atau hanya print(map(str, mylist))- ini sedikit lebih pendek
anula
4
Satu masalah dengan ini adalah jika item dalam daftar saya mungkin juga ada dalam daftar
Breandán Dalton
7

Dua hal mudah yang bisa Anda lakukan, gunakan mapfungsi atau gunakan pemahaman.

Tapi itu memberi Anda daftar string, bukan string. Jadi, Anda juga harus menggabungkan senar.

s= ",".join( map( str, myList ) )

atau

s= ",".join( [ str(element) for element in myList ] )

Kemudian Anda dapat mencetak objek string komposit ini.

print 'my list is %s'%( s )
S. Lott
sumber
4

Bergantung pada apa Anda ingin menggunakan output itu, mungkin __repr__lebih tepat:

import unittest

class A(object):
    def __init__(self, val):
        self.val = val

    def __repr__(self):
        return repr(self.val)

class Test(unittest.TestCase):
    def testMain(self):
        l = [A('a'), A('b')]
        self.assertEqual(repr(l), "['a', 'b']")

if __name__ == '__main__':
    unittest.main()
Horst Gutmann
sumber
3

Saya setuju dengan jawaban sebelumnya tentang menggunakan pemahaman daftar untuk melakukan ini, tetapi Anda pasti bisa menyembunyikannya di balik suatu fungsi, jika itu yang mengapung perahu Anda.

def is_list(value):
    if type(value) in (list, tuple): return True
    return False

def list_str(value):
    if not is_list(value): return str(value)
    return [list_str(v) for v in value]

Hanya untuk bersenang-senang, saya membuat list_str () secara rekursif str () semua yang ada dalam daftar.

Jeremy Cantrell
sumber
+1 Ini berguna saat mengimplementasikan __str__dan __repr__secara terpisah
vincent gravitas
0

Sesuatu seperti ini?

a = [1, 2 ,3]
[str(x) for x in a]
# ['1', '2', '3']
Apa yang dia lakukan
sumber
0

Ini sudah cukup.

Saat mencetak daftar serta kelas wadah lainnya, elemen yang terkandung akan dicetak menggunakan __repr__, karena __repr__dimaksudkan untuk digunakan untuk representasi objek internal. Jika kita menelepon: help(object.__repr__)itu akan memberi tahu kita:

Help on wrapper_descriptor:

__repr__(self, /)
    Return repr(self).

Dan jika kita menyebutnya help(repr)akan menghasilkan:

Help on built-in function repr in module builtins:

repr(obj, /)
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.

Jika __str__diimplementasikan untuk sebuah objek dan __repr__tidak repr(obj)akan menampilkan keluaran default, seperti print(obj)saat yang bukan ini diimplementasikan.

Jadi satu-satunya cara adalah menerapkannya __repr__untuk kelas Anda. Salah satu cara yang mungkin untuk melakukannya adalah ini:

class C:           
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

C.__repr__=C.__str__       
ci = C()    


print(ci)       #C class str 
print(str(ci))  #C class str 
print(repr(ci)) #C class str 
prosti
sumber
-3

Output yang Anda dapatkan hanyalah nama modul objek, nama kelas, dan kemudian alamat memori dalam heksadesimal karena __repr__fungsinya tidak diganti.

__str__digunakan untuk representasi string suatu objek saat menggunakan print. Tapi karena Anda mencetak daftar objek, dan tidak mengulang daftar untuk memanggil strmetode untuk setiap item, itu mencetak representasi objek.

Agar __str__fungsi tersebut dipanggil, Anda perlu melakukan sesuatu seperti ini:

'my list is %s' % [str(x) for x in myList]

Jika Anda mengesampingkan __repr__fungsi, Anda dapat menggunakan metode cetak seperti sebelumnya:

class cell:
    def __init__(self, id):
        self.id = id
    def __str__(self):
        return str(self.id) # Or whatever
    def __repr__(self):
        return str(self) # function invoked when you try and print the whole list.

myList = [cell(1), cell(2), cell(3)]
'my list is %s' % myList

Kemudian Anda akan mendapatkan " my list is [1, 2, 3]" sebagai keluaran Anda.

panagiwtis koligas
sumber
Jawaban ini sepertinya menjawab pertanyaan yang sama sekali tidak berhubungan. Apakah Anda yakin telah meletakkannya di tempat yang benar?
Blckknght
ya Blckknght halaman ini yang ingin saya berikan jawaban saya memiliki tautan ke halaman ini dari posting lain. jadi itu membimbing saya ke sini dan saya menjawab di sini seandainya orang yang membuat pertanyaan itu akan datang ke sini lagi dan melihat jawaban saya .. maaf untuk ketidaknyamanan !!!
panagiwtis koligas
Jika pertanyaan lain ditutup sebagai duplikat dari pertanyaan ini, maka diasumsikan bahwa jawaban yang ada di sini seharusnya sudah menangani pertanyaan lain. Jika bukan itu masalahnya, Anda harus menandai untuk membuka kembali pertanyaan itu, daripada memposting jawaban yang tidak bisa dimengerti di sini, yang hampir pasti akan dihapus. Sekarang, mungkin Anda memiliki sesuatu untuk dikatakan yang tidak tercakup oleh salah satu dari 8 jawaban lain di sini, tetapi Anda harus membuat jawaban Anda masuk akal dalam konteks halaman ini, karena pertanyaan inilah yang Anda jawab. Dan jangan memposting dua jawaban yang identik!
Blckknght
1
Oh, meskipun sekarang setelah saya melihatnya lagi, tampaknya @charliebeckwith telah mengedit postingan Anda menjadi postingan yang sama sekali berbeda, daripada memposting jawaban mereka sendiri, karena alasan yang tidak dapat dijelaskan. Biasanya tidak seperti itu cara kerja pengeditan ...
Blckknght
@blckknght Saya mulai mengeditnya sebelum saya menyadari betapa salah jawabannya. Benar-benar tidak bisa dijelaskan mengapa saya terus berjalan.
charliebeckdengan