2013-06-04 30 views
9

ai có thể khai sáng cho tôi về sự khác biệt giữa print sthprint str(sth)?in trăn vs __str__?

Ví dụ: trong ví dụ từ official documentation for sqlite3, một hiện có thể nhìn thấy đoạn mã sau đó tạo ra một cơ sở dữ liệu và sau đó sử dụng một lớp nhà máy để quấn dữ liệu được chiết xuất từ ​​đó:

(1) Tạo một cơ sở dữ liệu:

# I am using CPython 2.7, but I suppose 2.6 will be Ok as well 
import sqlite3 
conn = sqlite3.connect(":memory:") 
c = conn.cursor() 

c.execute('''create table stocks 
(date text, trans text, symbol text, qty real, price real)''') 
c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""") 
conn.commit() 

c.close() 

(2) Bây giờ sử dụng máy để sản xuất một số đối tượng:

>>> conn.row_factory = sqlite3.Row 
>>> c = conn.cursor() 

>>> c.execute('select * from stocks') 
<sqlite3.Cursor object at 0x7f4e7dd8fa80> 
>>> r = c.fetchone() 
>>> type(r) 
<type 'sqlite3.Row'> 
>>> r 
(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14) 

Như bạn thấy, chúng ta có thể gõ r, hoặc print r để có được đại diện tốt đẹp của các đối tượng liên tiếp.

Nhưng những gì không được hiển thị ở trên, nó là print str(r) sẽ cung cấp cho bạn một cái gì đó khác nhau - một cái gì đó giống như:

<sqlite3.Row object at 0x7f4e7dd8abcd> 

Vì vậy, tôi tự hỏi, nếu một người nào đó nổi làm quen với thực hiện CPython có thể giải thích những gì in không đến có được loại đại diện này từ một đối tượng không hỗ trợ __str__? Hoặc tôi đoán một câu hỏi khác sẽ là - trong trường hợp các biểu thức trên cho kết quả khác nhau - làm cách nào tôi có thể nhận được một chuỗi tương đương với một chuỗi được in đơn giản print obj?

+0

có thể trùng lặp của [Làm thế nào có thể in một kết quả đối tượng trong đầu ra khác nhau hơn cả str() và repr()?] (Http: //stackoverflow.com/questions/7920284/how-can-printing-an-object-result-in-different-output-than-both-str-and-repr) –

+0

Sao chép câu trả lời của bạn ở đó, sửa đổi một dòng để tránh người kiểm duyệt câu trả lời song song và chúng ta hãy đóng này :-) –

Trả lời

7

Trong khi tôi đang viết những dòng này và tìm kiếm một số tài liệu tham khảo, tôi đã thực sự tìm thấy hầu hết các phần của câu trả lời:

  1. việc thực hiện C cho một đối tượng Python có thể thực hiện PyObject_Print() chức năng, trong đó xác định đường đi đối tượng sẽ được in ra một tệp, bao gồm stdout;

  2. Vì vậy, để có được đại diện đó, có lẽ nên sử dụng mô-đun cStringIO (chưa thử, nhưng được cho là sẽ hoạt động).

Tuy nhiên, tôi sẽ để câu hỏi này ở đây với hy vọng ai đó có thể thấy hữu ích - hoặc cung cấp câu trả lời tốt hơn.

Cập nhật. Một ví dụ cStringIO:

import cStringIO as C; s = C.StringIO(); print >>s, r, ; s.getvalue() 

- dấu phẩy cuối cùng giúp để thoát khỏi kí tự xuống dòng (s) [những gì tôi cho rằng phụ thuộc vào nền tảng này]

PS. Vài câu hỏi nào liên quan ở đây trên SO:
- "Python print isn't using __repr__, __unicode__ or __str__ for unicode subclass?"
- "Difference between __str__ and __repr__ in Python?"

(. Ví dụ, answer trả lời câu hỏi đầu tiên của có đẹp link này vào mã của PyFile_WriteObject())

PPS. Trong py3k, sự khác biệt này seems to be gone completely.

3

Đây là sự khác biệt giữa __str____repr__

Cả hai phương pháp này sẽ trả về một chuỗi đại diện cho các đối tượng, nhưng:

  • __repr__nên trả về một expresion Python hợp lệ hoặc một cái gì đó giống như <....> nếu nó có thể Không sản xuất ra rằng
  • __str__có thể trả lại thêm người dùng thân thiện chuỗi

Chính thức, print sth nếu giống như print repr(sth):

>>> class C: 
... def __str__(self): 
...  return "__str__" 
... def __repr__(self): 
...  return "__repr__" 
... 
>>> c = C() 
>>> c 
__repr__ 
>>> print c 
__str__ 
>>> `c` 
'__repr__' 
>>> repr(c) 
'__repr__' 
>>> str(c) 
'__str__' 

Liên quan đến tuyên bố print, If an object is not a string, it is first converted to a string using the rules for string conversions và liên quan đến chuỗi quy tắc chuyển đổi: The built-in function repr() performs exactly the same conversion in its argument as enclosing it in parentheses and reverse quotes does. The built-in function str() performs a similar but more user-friendly conversion.


EDIT: Về trường hợp cụ thể được trích dẫn làm ví dụ, có vẻ như at C-levelsqlite3.row định nghĩa PyTypeObject.tp_print làm con trỏ đến chức năng in tùy chỉnh chuyển tiếp tới PyTuple_Type.tp_print. Trong cùng một thời điểm, tp_strtp_repr không được xác định trước - một dự phòng sẽ áp dụng cho hành vi in ​​đối tượng mặc định như được quan sát.

Kết luận, với trăn 2.x, print(obj), print(str(obj))print(repr(obj)) có khả năng tạo ra ba kết quả khác nhau.

Sự khác biệt này dường như đã được nâng lên ở mức 3.x khi tuyên bố in trở thành chức năng bình thường.

# In Python 3.3: 
>>> print(r) 
<sqlite3.Row object at 0x7f4cedfbffd0> 
>>> print(repr(r)) 
<sqlite3.Row object at 0x7f4cedfbffd0> 
>>> print(str(r)) 
<sqlite3.Row object at 0x7f4cedfbffd0> 

EDIT2: Tuy nhiên liên quan đến trường hợp cụ thể của sqlite3.Row, dường như liên tiếp có thể được chuyển đổi sang một tuple. Tôi đã thử nghiệm nó cả với Python 2.6 và 3.3.

Python 2.6:

>>> sys.version 
'2.6.6 (r266:84292, Dec 26 2010, 22:31:48) \n[GCC 4.4.5]' 
>>> type(r) 
<type 'sqlite3.Row'> 
>>> r 
(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.140000000000001) 
>>> tuple(r) 
(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.140000000000001) 
>>> repr(tuple(r)) 
"(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.140000000000001)" 

Python 3.3:

>>> sys.version 
'3.3.1 (default, May 28 2013, 18:34:21) \n[GCC 4.4.5]' 
>>> type(r) 
<type 'sqlite3.Row'> 
>>> r 
<sqlite3.Row object at 0x7f4cedfbffd0> 
>>> tuple(r) 
('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14) 
>>> repr(tuple(r)) 
"('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14)" 
+1

"Chính thức," in sth' nếu giống như 'print str (sth)' "(có một lỗi chính tả rõ ràng trong văn bản của bạn, 'str' <-> 'repr') Đó chính xác là cái gì của tôi sự hiểu biết về chủ đề trước khi tôi nhận thấy rằng đối với mã từ câu hỏi, không phải các hàm 'str()' và 'repr()' sẽ không tạo ra kết quả tương tự như 'c = cStringIO.StringIO(); in >> c ...; c.getvalue() ' –

+0

Khi bạn nhận thấy hàm' PyObject_Print() 'cho phép các đối tượng gốc thực hiện hành vi _print của riêng chúng mà không dựa vào repr/str. Ý kiến ​​của tôi là nó có phần là một ý tưởng tồi vì nó không cho phép người ta dễ dàng lấy lại giá trị đó trong một biến. Hay tôi đang thiếu một cái gì đó? –

+0

Tôi có xu hướng đồng ý. Nhưng câu hỏi của tôi là nhiều hơn về cách mọi thứ được thực hiện hơn là làm thế nào họ nên có (và, lặp lại, đó là một chút bất ngờ, vì tôi cũng nghĩ rằng 'in' và' in str' là nhiều hơn hoặc ít hơn tương đương). –