Làm thế nào để in các thể hiện của một lớp bằng print ()?


538

Tôi đang học các sợi dây trong Python. Khi tôi cố gắng in một đối tượng của lớp Foobarbằng print()hàm, tôi nhận được một đầu ra như thế này:

<__main__.Foobar instance at 0x7ff2a18c>

Có cách nào để tôi có thể thiết lập hành vi in (hoặc biểu diễn chuỗi ) của một lớp và các đối tượng của nó không? Ví dụ, khi tôi gọi print()một đối tượng lớp, tôi muốn in các thành viên dữ liệu của nó theo một định dạng nhất định. Làm thế nào để đạt được điều này trong Python?

Nếu bạn đã quen thuộc với các lớp C ++, có thể đạt được những điều trên cho tiêu chuẩn ostreambằng cách thêm một friend ostream& operator << (ostream&, const Foobar&)phương thức cho lớp.

Câu trả lời:


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

Các __str__phương pháp là những gì sẽ xảy ra khi bạn in nó, và các __repr__phương pháp là những gì xảy ra khi bạn sử dụng repr()chức năng (hoặc khi bạn nhìn vào nó với dấu nhắc tương tác). Nếu đây không phải là phương pháp Pythonic nhất , tôi xin lỗi, vì tôi vẫn đang học - nhưng nó hiệu quả.

Nếu không có __str__phương thức nào được đưa ra, Python sẽ in kết quả __repr__thay thế. Nếu bạn xác định __str__nhưng không __repr__, Python sẽ sử dụng những gì bạn thấy ở trên là __repr__, nhưng vẫn sử dụng __str__để in.


11
cũng có một phương thức unicode mà bạn có thể sử dụng thay vì Str ; lưu ý rằng nó sẽ trả về một đối tượng unicode, không phải là một chuỗi (nhưng nếu bạn trả về một chuỗi, việc chuyển đổi thành unicode sẽ được thực hiện bằng mọi cách ...)
kender

@kender - Tôi không biết về nó, nhưng nhìn lại, nó hoàn toàn hợp lý khi xử lý Unicode bị hỏng của Python 2.x.
Chris Lutz

11
Tôi nghĩ rằng câu trả lời này không thể được hoàn thành mà không có liên kết đến câu hỏi khác !
tnotstar

Cứu tôi! Tuy nhiên, sau khi thực hiện lại phương thức __Vpr __ (tự), bản in sẽ đánh lừa người dùng. Bạn có biết về bất kỳ thực hành tốt nhất xung quanh này?
Việt

10
Đối với các lập trình viên Java: __str __ (tự) giống như toString () của thế giới trăn
Janac Meena

134

Như Chris Lutz đã đề cập , điều này được xác định bởi __repr__phương thức trong lớp của bạn.

Từ các tài liệu của repr():

Đối với nhiều loại, hàm này thực hiện một nỗ lực trả về một chuỗi sẽ mang lại một đối tượng có cùng giá trị khi được truyền vào eval(), nếu không, biểu diễn là một chuỗi được đặt trong dấu ngoặc nhọn chứa tên của loại đối tượng cùng với thông tin bổ sung thường bao gồm tên và địa chỉ của đối tượng. Một lớp có thể kiểm soát những gì hàm này trả về cho các thể hiện của nó bằng cách định nghĩa một __repr__()phương thức.

Cho bài kiểm tra lớp sau:

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 sẽ hành động theo cách sau trong trình bao 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

Nếu không có __str__phương thức nào được xác định, print(t)(hoặc print(str(t))) sẽ sử dụng kết quả __repr__thay thế

Nếu không có __repr__phương thức nào được xác định thì mặc định được sử dụng, tương đương với ..

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))

+1 nhưng mã lớp của bạn __str__khác với kết quả của lớp vỏ tương tác mà bạn đưa ra. : P
Chris Lutz

1
Err, oops .. sửa đổi thủ công đầu ra REPL không bao giờ kết thúc tốt. Tôi có lẽ nên ghi lại các bài đăng của mình: P
dbr

1
Định %dạng chuỗi không bị phản đối, từ docs.python.org/whatsnew/2.6.html "toán tử% được bổ sung bằng phương thức định dạng chuỗi mạnh hơn, định dạng ()"
dbr

4
Dbr: Đó là sự thật. Xin lưu ý rằng tài liệu "What New New Python Python" cũng nói "phương thức format () [...] Kế hoạch cuối cùng là biến API này thành định dạng chuỗi và bắt đầu từ chối toán tử% trong Python 3.1."
Ashwin Nanjappa

1
Thật đáng tiếc, %thật tiện lợi.
Janusz Lenar

52

Một cách chung có thể được áp dụng cho bất kỳ lớp nào mà không có định dạng cụ thể có thể được thực hiện như sau:

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__)

Và sau đó,

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

sản xuất

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

23

Nếu bạn đang ở trong một tình huống như @Keith, bạn có thể thử:

print a.__dict__

Nó đi ngược lại với những gì tôi sẽ xem là phong cách tốt nhưng nếu bạn chỉ đang cố gắng gỡ lỗi thì nó sẽ làm những gì bạn muốn.


Bạn có biết làm thế nào để biết nếu khóa dict có các đối tượng trong các giá trị của nó không?
pranaygoyalty02

1
@HadoopEveachist Bạn đang hỏi làm thế nào để in đệ quy những đối tượng đó hay chỉ xác định xem có đối tượng không?
Giăng

13

Chỉ cần thêm hai xu của tôi vào câu trả lời của @ dbr, sau đây là một ví dụ về cách triển khai câu này từ tài liệu chính thức mà anh ấy trích dẫn:

"[...] để trả về một chuỗi sẽ mang lại một đối tượng có cùng giá trị khi được truyền cho eval (), [...]"

Đưa ra định nghĩa lớp này:

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)

Bây giờ, dễ dàng để tuần tự hóa thể hiện của Testlớp:

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

Vì vậy, chạy đoạn mã cuối cùng, chúng ta sẽ nhận được:

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")

Nhưng, như tôi đã nói trong bình luận cuối cùng của tôi: nhiều thông tin hơn chỉ ở đây !


12

Bạn cần sử dụng __repr__. Đây là một chức năng tiêu chuẩn như thế nào __init__. Ví dụ:

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

2
reprstr có ngữ nghĩa khác nhau: repr phải là nguồn Python sẽ tạo lại cùng một đối tượng - đây là ý nghĩa lặp lại của nó trong mã; str nên là một chuỗi người dùng đẹp của đối tượng.
Tháp Eric

12

Phiên bản phản hồi đẹp hơn của @ 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)

Sản xuất danh sách trực quan tốt đẹp của tên và giá trị.

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

Một phiên bản thậm chí còn lạ hơn (cảm ơn Ruud) sắp xếp các mục:

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

8

Đối với Python 3:

Nếu định dạng cụ thể không quan trọng (ví dụ để gỡ lỗi), chỉ cần kế thừa từ lớp Có thể in bên dưới. Không cần phải viết mã cho mọi đối tượng.

Lấy cảm hứng từ câu trả lời này

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)

1

Đã có rất nhiều câu trả lời trong chủ đề này nhưng không có câu trả lời nào đặc biệt giúp tôi, tôi phải tự mình giải quyết nó, vì vậy tôi hy vọng câu hỏi này có nhiều thông tin hơn.

Bạn chỉ cần đảm bảo rằng bạn có dấu ngoặc đơn ở cuối lớp, ví dụ:

print(class())

Đây là một ví dụ về mã từ một dự án tôi đang thực hiện:

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")

Để in lớp Hydrogen của tôi, tôi đã sử dụng như sau:

print(Hydrogen())

Xin lưu ý, điều này sẽ không hoạt động nếu không có dấu ngoặc đơn ở cuối Hydrogen. Chúng là cần thiết.

Hy vọng điều này sẽ giúp, cho tôi biết nếu bạn có câu hỏi nữa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.