Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python print vs __str__?

can anyone enlighten me on the differences between print sth and print str(sth) ?

E.g. in the example from the official documentation for sqlite3, one can currently see the following code that creates a database and then uses a factory class to wrap data extracted from there:

(1) Create a database:

# 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) Now using the Row factory to produce some objects:

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

As you see, we can type r, or print r to get this nice representation of the row object.

But what is not shown above, it is that print str(r) will give you something different -- something more like:

<sqlite3.Row object at 0x7f4e7dd8abcd> 

So I wonder if someone well-acquainted with CPython implementation can explain what print does to obtain this kind of representation from an object that does not support __str__ ?

Or I guess an alternative question would be -- in the case when the above expressions give different results -- how I can obtain a string equivalent to the one that would be printed with simple print obj ?

like image 323
ジョージ Avatar asked Jun 04 '13 09:06

ジョージ


2 Answers

While I was writing this and looking for some references, I have actually found the most part of the answer:

  1. the C implementation for a Python object may implement PyObject_Print() function, which defines the way the object will be printed to a file, including stdout;

  2. So to get that representation, one should probably use the cStringIO module (didn't try that yet, but supposedly this should work).

Nevertheless, I will leave this question here in a hope that someone may find it useful -- or provide a better answer.

Upd. A cStringIO example:

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

-- the last comma helps to get rid of the newline character(s) [ what I suppose depends on the platform ]

PS. Couple of somewhat related questions here on SO:
-- "Python print isn't using __repr__, __unicode__ or __str__ for unicode subclass?"
-- "Difference between __str__ and __repr__ in Python?"

( For example, the first question's answer answer has this nice link to the code of PyFile_WriteObject() . )

PPS. In py3k, this discrepancy seems to be gone completely.

like image 178
ジョージ Avatar answered Nov 11 '22 03:11

ジョージ


This is the difference between __str__ and __repr__

Both methods will return a string representing the object, but:

  • __repr__ should return a valid Python expresion or something like <....> if it can't produce that
  • __str__ could return a more user friendly string

Formally, print sth if the same as 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__'

Concerning the print statement, If an object is not a string, it is first converted to a string using the rules for string conversions and concerning string conversion rules : 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: Concerning the specific case cited as an example, it appears that at C-level sqlite3.row defines PyTypeObject.tp_print as a pointer to a custom printing function that forwards to PyTuple_Type.tp_print. In the same time, tp_str and tp_repr are left undefined -- an so will fallback to the default object print behavior as observed.

As a conclusion, with python 2.x, print(obj), print(str(obj)) and print(repr(obj)) have the potential to produce three different results.

This discrepancy seems to have been lifted in 3.x as the print statement became a normal function.

# 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: Still concerning the specific case of sqlite3.Row, it appears that a row could be converted to a tuple. I have tested it both with Python 2.6 and 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)"
like image 35
Sylvain Leroux Avatar answered Nov 11 '22 02:11

Sylvain Leroux