2013-06-04 4 views
9

может кто-нибудь просветить меня по разнице между print sth и print str(sth)?python print vs __str__?

E.g. в примере из official documentation for sqlite3, можно в настоящее время увидеть следующий код, который создает базу данных, а затем использует класс фабрики, чтобы обернуть данные, извлеченные оттуда:

(1) Создание базы данных:

# 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) Теперь, используя завод по производству некоторых объектов:

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

Как вы видите, мы можем ввести r или print r, чтобы получить это милое представление объекта строки.

Но что не было показано выше, это то, что print str(r) даст вам что-то другое - что-то больше похоже:

<sqlite3.Row object at 0x7f4e7dd8abcd> 

Так мне интересно, если кто-то хорошо знакомы с реализацией CPython может объяснить, что печать делает для получить такой вид представления от объекта, который не поддерживает __str__?

Или я предполагаю, что альтернативный вопрос будет - в случае, когда приведенные выше выражения дают разные результаты - как я могу получить строку, эквивалентную той, которая была бы напечатана простым print obj?

+0

Возможный дубликат [Как печатая результат объекта в другом выходе, чем и ул() и магнезии()?] (HTTP: //stackoverflow.com/questions/7920284/how-can-printing-an-object-result-in-different-output-than-both-str-and-repr) –

+0

Скопируйте свой ответ там, измените одну строку, чтобы избежать модераторов ответов модераторов, и давайте Закройте это :-) –

ответ

7

Пока я пишу это и ищу некоторые ссылки, я действительно нашел большую часть ответа:

  1. реализации C для объекта Python может реализовывать PyObject_Print() функции, которая определяет способ объект будет напечатан в файле, включая stdout;

  2. Чтобы получить это представление, следует, вероятно, использовать модуль cStringIO (еще не пробовал, но предположительно это должно работать).

Тем не менее, я оставлю этот вопрос здесь в надежде, что кто-то найдет его полезным - или предоставит лучший ответ.

Обновление.cStringIO пример:

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

- последняя запятая помогает избавиться от символа новой строки (ов) [то, что я полагаю, зависит от платформы]

PS. Пара несколько связанных с этим вопросов здесь, на SO:
- "Python print isn't using __repr__, __unicode__ or __str__ for unicode subclass?"
- "Difference between __str__ and __repr__ in Python?"

(. Например, answer ответ на первый вопрос, имеет этот приятный link к коду PyFile_WriteObject())

PPS. В py3k это несоответствие seems to be gone completely.

3

Это разница между __str__ и __repr__

Оба метода возвращает строку, представляющую объект, но:

  • __repr__должен вернуть действительный expresion Python или что-то вроде <....>, если она может не производить
  • __str__can возвращение еще пользователь дружественных строка

Формально print sth если же, как 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__' 

Относительно print заявление, If an object is not a string, it is first converted to a string using the rules for string conversions и относительно правил преобразования строк: 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: Что касается конкретного случая, приведенного в качестве примера, то представляется, что at C-levelsqlite3.row определяет PyTypeObject.tp_print как указатель на пользовательскую функцию печати, которая пересылается до PyTuple_Type.tp_print. В то же время tp_str и tp_repr остаются неопределенными - так будет возвращаться к поведению объекта по умолчанию, как это наблюдается.

В заключение, с python 2.x, print(obj), print(str(obj)) и print(repr(obj)) имеют потенциал для получения трех разных результатов.

Это расхождение, кажется, были сняты в 3.x в заявлении печати стала нормальной функция.

# 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: Тем не менее в отношении конкретного случая sqlite3.Row, оказывается, что строка может быть преобразован в кортеж. Я тестировал его как с Python 2.6, так и с 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

«Формально,' print sth', если это так же, как 'print str (sth)' "(в вашем тексте есть очевидная опечатка, 'str' <-> 'repr') Именно это и было моим понимание предмета, прежде чем я заметил, что, например, для кода из вопроса ни функции 'str()', ни функции 'repr()' не будут давать тот же результат, что и 'c = cStringIO.StringIO(); print >> c ...; c.getvalue() ' –

+0

Как вы заметили, функция' PyObject_Print() 'позволяет собственным объектам реализовывать свое собственное поведение _print_, не полагаясь на repr/str. Мое мнение состоит в том, что это довольно плохая идея, поскольку она не позволяет легко вернуть это значение в переменную. Или я чего-то не хватает? –

+0

Я склонен согласиться. Но мой вопрос был скорее о том, как реализованы вещи, чем о том, как они должны были быть (и, повторяю, это было немного неожиданностью, поскольку я также думал, что «print» и «print str» более или менее эквивалентны). –

Смежные вопросы