Mục đích của __str__ và __repr__ là gì?


82

Tôi thực sự không hiểu ở đâu __str____repr__được sử dụng trong Python. Ý tôi là, tôi nhận được nó __str__trả về biểu diễn chuỗi của một đối tượng. Nhưng tại sao tôi cần điều đó? Trong trường hợp sử dụng kịch bản nào? Ngoài ra, tôi đã đọc về việc sử dụng__repr__

Nhưng điều tôi không hiểu là, tôi sẽ sử dụng chúng ở đâu?



4
Đối với bất kỳ ai đến từ Ruby, tl; dr là: __str__= to_s__repr__= inspect.
Ajedi32

Câu trả lời:


86

__repr__

Được gọi bằng repr()hàm tích hợp và bằng cách chuyển đổi chuỗi (dấu ngoặc kép) để tính toán biểu diễn chuỗi "chính thức" của một đối tượng. Nếu có thể, điều này sẽ trông giống như một biểu thức Python hợp lệ có thể được sử dụng để tạo lại một đối tượng có cùng giá trị (được cung cấp một môi trường thích hợp).

__str__

Được gọi bởi str()hàm tích hợp và bởi câu lệnh in để tính toán biểu diễn chuỗi "không chính thức" của một đối tượng.

Sử dụng __str__nếu bạn có một lớp và bạn sẽ muốn có một đầu ra thông tin / không chính thức, bất cứ khi nào bạn sử dụng đối tượng này như một phần của chuỗi. Ví dụ: bạn có thể xác định __str__các phương thức cho các mô hình Django, sau đó các phương thức này sẽ được hiển thị trong giao diện quản trị Django. Thay vì những thứ như <Model object>bạn sẽ nhận được như họ và tên của một người, tên và ngày của một sự kiện, v.v.


__repr____str__tương tự nhau, trên thực tế đôi khi bằng nhau (Ví dụ từ BaseSetlớp trong sets.pytừ thư viện chuẩn):

def __repr__(self):
    """Return string representation of a set.

    This looks like 'Set([<list of elements>])'.
    """
    return self._repr()

# __str__ is the same as __repr__
__str__ = __repr__

1
Cảm ơn! Điều này thật đúng với gì mà tôi đã tìm kiếm!
Daniel

`return self._repr ()` làm gì, khi tôi chạy mã và cố gắng hiểu nó nói __repr __ () nhận chính xác một đối số.
sáng

Vì vậy, tôi có thể sử dụng __repr__thay vì __str__django?
Amit Tripathi

60

Một nơi mà bạn sử dụng chúng nhiều là trong một phiên tương tác. Nếu bạn in một đối tượng thì __str__phương thức của nó sẽ được gọi, trong khi nếu bạn chỉ sử dụng một đối tượng thì nó __repr__được hiển thị:

>>> from decimal import Decimal
>>> a = Decimal(1.25)
>>> print(a)
1.25                  <---- this is from __str__
>>> a
Decimal('1.25')       <---- this is from __repr__

Mục __str__đích là để con người dễ đọc nhất có thể, trong khi __repr__mục đích là thứ có thể được sử dụng để tạo lại đối tượng, mặc dù nó thường không giống chính xác cách nó được tạo ra, như trong trường hợp này.

Cũng không có gì lạ khi cả hai __str____repr__trả về cùng một giá trị (chắc chắn là đối với các loại tích hợp sẵn).


Cảm ơn cho ví dụ này, đã cho tôi hiểu rõ hơn về nơi này được sử dụng bởi mặc định
JayRizzo

17

Grasshopper, khi có nghi ngờ, hãy đi lên núiđọc các Văn bản cổ . Trong chúng, bạn sẽ thấy rằng __repr __ () nên:

Nếu có thể, điều này sẽ giống như một biểu thức Python hợp lệ có thể được sử dụng để tạo lại một đối tượng có cùng giá trị.


6
-1 vì điều này thậm chí không cố gắng trả lời câu hỏi thực tế, đó là các trường hợp sử dụng là gì.
Scott Griffiths

4
@Scott: Bạn nói đúng. Nhưng sau đó, một lần nữa câu hỏi thực tế cho thấy hoàn toàn không có nỗ lực nào để truy cập tài liệu chính ngay từ đầu. Việc đặt một câu hỏi cho thấy bạn đã cố gắng trả lời cho chính mình là một điều nhưng vẫn còn hơi bối rối về một số khía cạnh của nó, và một điều khác hoàn toàn là đăng một câu hỏi như thế này. Chỉ cần gõ vào dòng chủ đề của anh ấy là một câu hỏi mới cho thấy rằng 5 trong số 6 chủ đề SO được đề xuất hàng đầu sẽ trả lời câu hỏi của anh ấy, nhưng anh ấy không thể bị làm phiền. Tôi đã không hoàn toàn cho anh ta một câu trả lời dễ hiểu, nhưng tôi đã bị cám dỗ rất nhiều.
Peter Rowell

1
Trên thực tế, anh ấy đã nói rằng anh ấy đã đọc về nó __repr__, các tài liệu chính thức không thực sự trả lời câu hỏi tại sao bạn sử dụng nó, và chỉ vì một câu hỏi được trả lời ở nơi khác không phải là lý do chính đáng để nó cũng không được đã trả lời trên SO (thường xuyên không phải Google sẽ đưa bạn trở lại đây!) Nếu bạn không nghĩ rằng câu hỏi nào đáng trả lời thì bạn không thể trả lời nó, mặc dù trong trường hợp này, tôi đồng ý rằng nó đã được đề cập rất tốt. SO và vì vậy liên kết đến các bản sao sẽ là một phản ứng thích hợp.
Scott Griffiths

Trên thực tế, bạn không chính xác. Tài liệu cho biết rõ ràng lý do tại sao bạn sẽ sử dụng nó, hóm hỉnh: "Cái này thường được sử dụng để gỡ lỗi, vì vậy điều quan trọng là phần trình bày phải giàu thông tin và rõ ràng." Tôi đã thấy quá nhiều diễn đàn (diễn đàn?) Chìm dưới sức nặng của Ma cà rồng trợ giúp và tôi thật đau lòng khi thấy nó bắt đầu được truyền lại. Đối với việc liên kết đến các câu trả lời SO rõ ràng khác, đó là toàn bộ mục đích của cơ chế gợi ý khởi động khi bạn nhập vào dòng Chủ đề của mình, nhưng anh ấy đã chọn bỏ qua tất cả các đề xuất. QED & PDQ cũng vậy.
Peter Rowell

5
Chà, tài liệu vẫn không nói cách sử dụng nó để gỡ lỗi, nhưng tôi thực sự không có ý định tranh luận về điều này. Ít nhất chúng tôi đồng ý rằng câu trả lời của bạn không giải quyết được câu hỏi, vì vậy -1 của tôi vẫn cảm thấy hợp lý với tôi. Nếu một câu hỏi được viết kém / trùng lặp / tầm thường thì bạn có thể giúp cải thiện câu hỏi, liên kết đến các câu hỏi trùng lặp hoặc đơn giản là bỏ phiếu cho câu hỏi. Tôi nghĩ sự phản đối chính của tôi ở đây là câu trả lời nên cố gắng trả lời câu hỏi - có những cơ chế khác để chỉ trích câu hỏi. Tôi sẽ im lặng ngay bây giờ vì tôi nghĩ cả hai chúng ta đều có nhiều việc tốt hơn để làm ở đây.
Scott Griffiths

14

Xây dựng và dựa trên các câu trả lời trước đó và hiển thị thêm một số ví dụ. Nếu được sử dụng đúng cách, sự khác biệt giữa strreprlà rõ ràng. Trong ngắn hạn, reprsẽ trả về một chuỗi có thể được sao chép-dán để xây dựng lại trạng thái chính xác của đối tượng, trong khi strnó hữu ích cho loggingobservinggỡ lỗi kết quả. Dưới đây là một số ví dụ để xem các kết quả đầu ra khác nhau cho một số thư viện đã biết.

Ngày giờ

print repr(datetime.now())    #datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)
print str(datetime.now())     #2017-12-12 18:49:27.134452

Các strlà tốt để in vào một tập tin nhật ký, nơi như reprcó thể tái có mục tiêu nếu bạn muốn chạy nó trực tiếp hoặc đổ nó như lệnh vào một file.

x = datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)

Numpy

print repr(np.array([1,2,3,4,5])) #array([1, 2, 3, 4, 5])
print str(np.array([1,2,3,4,5]))  #[1 2 3 4 5]

trong Numpy, reprmột lần nữa được tiêu thụ trực tiếp.

Ví dụ về Vector3 tùy chỉnh

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

Trong ví dụ này, reprtrả lại một chuỗi có thể được sử dụng / thực thi trực tiếp, trong khi strnó hữu ích hơn như một đầu ra gỡ lỗi.

v = Vector3([1,2,3])
print str(v)     #x: 1, y: 2, z: 3
print repr(v)    #Vector3([1,2,3])

Một điều cần lưu ý, nếu strkhông được định nghĩa nhưng repr, strsẽ tự động gọi repr. Vì vậy, tốt nhất là nên xác địnhrepr


5

Cho phép có một lớp không có __str__chức năng.

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

emp1 = Employee('Ivan', 'Smith', 90000)

print(emp1)

Khi chúng tôi in phiên bản này của lớp emp1, đây là những gì chúng tôi nhận được:

<__main__.Employee object at 0x7ff6fc0a0e48>

Điều này không hữu ích lắm và chắc chắn đây không phải là những gì chúng tôi muốn in nếu chúng tôi đang sử dụng nó để hiển thị (như trong html)

Vì vậy, bây giờ, cùng một lớp, nhưng với __str__chức năng:

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

    def __str__(self):
        return(f"The employee {self.first} {self.last} earns {self.pay}.")
        # you can edit this and use any attributes of the class

emp2 = Employee('John', 'Williams', 90000)

print(emp2)

Bây giờ thay vì in rằng có một đối tượng, chúng tôi nhận được những gì chúng tôi đã chỉ định với trả về của __str__hàm:

The employee John Williams earns 90000


3

strsẽ là định dạng không chính thức và có thể đọc được trong khi reprsẽ cung cấp đại diện đối tượng chính thức.

class Complex:
    # Constructor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # "official" string representation of an object
    def __repr__(self):
        return 'Rational(%s, %s)' % (self.real, self.imag)

    # "informal" string representation of an object (readable)
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

    t = Complex(10, 20)

    print (t)     # this is usual way we print the object
    print (str(t))  # this is str representation of object 
    print (repr(t))  # this is repr representation of object   

Answers : 

Rational(10, 20) # usual representation
10 + i20      # str representation
Rational(10, 20)  # repr representation

1

strrepr là cả hai cách để biểu diễn. Bạn có thể sử dụng chúng khi bạn đang viết một lớp học.

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __repr__(self):
    return "{}/{}".format(self.n, self.d)

ví dụ khi tôi in một phiên bản của nó, nó sẽ trả về những thứ.

print(Fraction(1, 2))

kết quả trong

1/2

trong khi

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "{}/{}".format(self.n, self.d)
print(Fraction(1, 2))

cũng dẫn đến

1/2

Nhưng nếu bạn viết cả hai, python sử dụng cái nào?

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "str"
def __repr__(self):
    return "repr"

print(Fraction(None, None))

Kết quả này trong

str

Vì vậy, python thực sự sử dụng phương thức str không phải phương thức repr khi cả hai được viết.


Điều này có hiệu quả không?
KingWitherBrine
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.