python print vs __str__?

时间:2013-06-04 09:50:35

标签: python python-2.7

任何人都可以了解print sthprint str(sth)之间的差异吗?

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)现在使用Row工厂生成一些对象:

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

如您所见,我们可以输入rprint r来获得行对象的漂亮表示。

但是上面没有显示的是print str(r)会给你一些不同的东西 - 更像是:

<sqlite3.Row object at 0x7f4e7dd8abcd> 

所以我想知道一个熟悉CPython实现的人是否可以解释什么打印从不支持__str__的对象中获取这种表示?

或者我想另一个问题是 - 在上述表达式给出不同结果的情况下 - 我如何获得一个等同于用简单print obj打印的字符串的字符串?

2 个答案:

答案 0 :(得分:7)

当我写这篇文章并寻找一些参考文献时,我实际上找到了答案的大部分内容:

  1. Python对象的C实现可以实现PyObject_Print()函数,该函数定义了对象打印到文件的方式,包括stdout;

  2. 因此,要获得该表示,应该使用cStringIO模块(尚未尝试过,但据说这应该有效)。

  3. 尽管如此,我会在这里留下这个问题,希望有人觉得它有用 - 或提供更好的答案。

    更新。一个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

答案 1 :(得分:3)

这是__str____repr__

之间的差异

两种方法都将返回表示对象的字符串,但是:

  • __repr__ 应该返回有效的Python表达式或类似<....>的内容,如果它无法生成
  • __str__ 可以返回更多用户友好字符串

正式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.


编辑:关于作为示例引用的特定案例,at C-level sqlite3.row似乎将PyTypeObject.tp_print定义为指向自定义打印功能的指针到PyTuple_Type.tp_print。同时,tp_strtp_repr未定义 - 因此将回退到所观察到的默认对象打印行为。

作为结论,使用python 2.x,print(obj)print(str(obj))print(repr(obj))有可能产生三种不同的结果。

由于print 语句成为正常的函数,这种差异似乎已在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)"