Bagaimana cara mencetak instance kelas menggunakan print ()?

539

Saya belajar tali dengan Python. Ketika saya mencoba untuk mencetak objek kelas Foobarmenggunakan print()fungsi, saya mendapatkan output seperti ini:

<__main__.Foobar instance at 0x7ff2a18c>

Apakah ada cara saya bisa mengatur perilaku pencetakan (atau representasi string ) dari suatu kelas dan objeknya ? Misalnya, ketika saya memanggil print()objek kelas, saya ingin mencetak anggota datanya dalam format tertentu. Bagaimana cara mencapai ini dengan Python?

Jika Anda terbiasa dengan kelas C ++, hal di atas dapat dicapai untuk standar ostreamdengan menambahkan friend ostream& operator << (ostream&, const Foobar&)metode untuk kelas.

Ashwin Nanjappa
sumber

Jawaban:

629
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

The __str__metode adalah apa yang terjadi ketika Anda mencetaknya, dan __repr__metode adalah apa yang terjadi ketika Anda menggunakan repr()fungsi (atau ketika Anda melihat itu dengan cepat interaktif). Jika ini bukan metode Pythonic yang paling , saya minta maaf, karena saya masih belajar juga - tetapi berhasil.

Jika tidak ada __str__metode yang diberikan, Python akan mencetak hasil __repr__sebagai gantinya. Jika Anda mendefinisikan __str__tetapi tidak __repr__, Python akan menggunakan apa yang Anda lihat di atas sebagai __repr__, tetapi masih digunakan __str__untuk mencetak.

Chris Lutz
sumber
11
ada juga metode unicode , yang bisa Anda gunakan sebagai ganti Str ; catatan bahwa ia harus kembali objek unicode, bukan string (tetapi jika Anda kembali string, konversi ke unicode akan dilakukan pula ...)
kender
@kender - Saya tidak tahu tentang itu, tetapi kalau dipikir-pikir itu masuk akal mengingat penanganan Unicode yang rusak oleh Python 2.x.
Chris Lutz
11
Saya pikir jawaban ini tidak dapat diselesaikan tanpa tautan ke yang lain ini !
tnotstar
Menyelamatkan saya! Namun, setelah menerapkan kembali metode __repr __ (mandiri), hasil cetak akan menyesatkan pengguna. Apakah Anda mengetahui adanya praktik terbaik dalam hal ini?
Viet
10
Untuk programmer Java: __str __ (self) seperti toString () dari dunia python
Janac Meena
134

Seperti yang disebutkan Chris Lutz , ini didefinisikan oleh __repr__metode di kelas Anda.

Dari dokumentasi repr():

Untuk banyak jenis, fungsi ini berusaha untuk mengembalikan string yang akan menghasilkan objek dengan nilai yang sama ketika diteruskan ke eval(), jika representasi adalah string yang terlampir dalam kurung sudut yang berisi nama jenis objek bersama dengan informasi tambahan sering termasuk nama dan alamat objek. Kelas dapat mengontrol apa fungsi ini dikembalikan untuk instance-nya dengan mendefinisikan __repr__()metode.

Diberikan Tes kelas berikut:

class Test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "<Test a:%s b:%s>" % (self.a, self.b)

    def __str__(self):
        return "From str method of Test: a is %s, b is %s" % (self.a, self.b)

..it akan bertindak dengan cara berikut di shell Python:

>>> t = Test(123, 456)
>>> t
<Test a:123 b:456>
>>> print repr(t)
<Test a:123 b:456>
>>> print(t)
From str method of Test: a is 123, b is 456
>>> print(str(t))
From str method of Test: a is 123, b is 456

Jika tidak ada __str__metode yang didefinisikan, print(t)(atau print(str(t))) akan menggunakan hasil __repr__sebagai gantinya

Jika tidak ada __repr__metode yang didefinisikan maka default digunakan, yang cukup banyak setara dengan ..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))
dbr
sumber
+1 tetapi kode kelas Anda __str__berbeda dari hasil shell interaktif yang Anda berikan. : P
Chris Lutz
1
Err, oops .. memodifikasi secara manual output REPL tidak pernah berakhir dengan baik. Saya mungkin harus mendokumentasikan posting saya: P
dbr
1
The %format string tidak usang, dari docs.python.org/whatsnew/2.6.html "operator% adalah dilengkapi dengan string yang lebih kuat metode format (format)"
DBR
4
Dbr: Itu benar. Perhatikan bahwa "What's New In Python 3.0" doc juga mengatakan "format () metode [...] Rencananya adalah untuk akhirnya menjadikan ini satu-satunya API untuk pemformatan string, dan mulai mengurangi operator% dalam Python 3.1."
Ashwin Nanjappa
1
Pitty, %sudah sangat nyaman.
Janusz Lenar
52

Cara umum yang dapat diterapkan ke kelas apa pun tanpa pemformatan tertentu dapat dilakukan sebagai berikut:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

Lalu,

elem = Element('my_name', 'some_symbol', 3)
print(elem)

menghasilkan

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}
pengguna394430
sumber
23

Jika Anda berada dalam situasi seperti @Keith, Anda dapat mencoba:

print a.__dict__

Itu bertentangan dengan apa yang saya anggap gaya yang baik tetapi jika Anda hanya mencoba untuk debug maka itu harus melakukan apa yang Anda inginkan.

John
sumber
Apakah Anda tahu cara mengetahui apakah kunci dict memiliki objek dalam nilainya?
pranaygoyal02
1
@HadoopEvangelist Apakah Anda bertanya bagaimana cara mencetak objek itu secara rekursif juga atau hanya menentukan apakah ada objek?
John
13

Hanya untuk menambahkan dua sen saya ke jawaban @ dbr, berikut ini adalah contoh bagaimana menerapkan kalimat ini dari dokumentasi resmi yang dikutipnya:

"[...] untuk mengembalikan string yang akan menghasilkan objek dengan nilai yang sama ketika diteruskan ke eval (), [...]"

Dengan definisi kelas ini:

class Test(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __str__(self):
        return "An instance of class Test with state: a=%s b=%s" % (self._a, self._b)

    def __repr__(self):
        return 'Test("%s","%s")' % (self._a, self._b)

Sekarang, mudah membuat serialisasi instance Testkelas:

x = Test('hello', 'world')
print 'Human readable: ', str(x)
print 'Object representation: ', repr(x)
print

y = eval(repr(x))
print 'Human readable: ', str(y)
print 'Object representation: ', repr(y)
print

Jadi, menjalankan potongan kode terakhir, kita akan mendapatkan:

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Tapi, seperti yang saya katakan di komentar terakhir saya: info lebih lanjut ada di sini !

tnotstar
sumber
12

Anda harus menggunakan __repr__. Ini adalah fungsi standar seperti __init__. Sebagai contoh:

class Foobar():
    """This will create Foobar type object."""

    def __init__(self):
        print "Foobar object is created."

    def __repr__(self):
        return "Type what do you want to see here."

a = Foobar()

print a
diagram alir
sumber
2
repr dan str memiliki semantik yang berbeda: repr harus menjadi sumber Python yang akan (kembali) membuat objek yang sama - ini adalah repr esentasinya dalam kode; str harus menjadi pengikat objek yang cantik.
Eric Towers
12

Versi respons yang lebih cantik oleh @ user394430

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return  str(self.__class__) + '\n'+ '\n'.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__))

elem = Element('my_name', 'some_symbol', 3)
print(elem)

Menghasilkan daftar nama dan nilai yang bagus secara visual.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

Versi yang lebih bagus (terima kasih Ruud) mengurutkan item:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))
MikeyB
sumber
8

Untuk Python 3:

Jika format spesifik tidak penting (misalnya untuk debugging), cukup mewarisi dari kelas Cetak di bawah ini. Tidak perlu menulis kode untuk setiap objek.

Terinspirasi oleh jawaban ini

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)

# Example Usage
class MyClass(Printable):
    pass

my_obj = MyClass()
my_obj.msg = "Hello"
my_obj.number = "46"
print(my_obj)
PeterM
sumber
1

Sudah ada banyak jawaban di utas ini tetapi tidak ada satupun yang secara khusus membantu saya, saya harus mengerjakannya sendiri, jadi saya harap yang ini sedikit lebih informatif.

Anda hanya perlu memastikan bahwa Anda memiliki tanda kurung di akhir kelas Anda, misalnya:

print(class())

Berikut adalah contoh kode dari proyek yang sedang saya kerjakan:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}\nAtomic Number: {}\n".format(self.name, self.symbol, self.number

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")

Untuk mencetak kelas Hidrogen saya, saya menggunakan yang berikut:

print(Hydrogen())

Harap dicatat, ini tidak akan berfungsi tanpa tanda kurung di akhir Hydrogen. Mereka perlu.

Semoga ini bisa membantu, beri tahu saya jika Anda memiliki pertanyaan lagi.

Kekar
sumber