Python “str”和“repr”之间有什么区别?

Python “str”和“repr”之间有什么区别?,python,magic-methods,repr,Python,Magic Methods,Repr,Python中的\uuu str\uuu和\uu repr\uuu有什么区别?来自effbot: \uuuu str\uuuuu计算对象的“非正式”字符串表示形式。这与\uuuuu repr\uuuuu不同,因为它不必是有效的Python表达式:可以使用更方便或简洁的表示形式。”\uuuu repr\uuuu:python对象的表示形式通常eval会将其转换回该对象 \uuuu str\uuuuu:是您认为文本形式的对象 e、 g >>s=“”w'o“w”“” >>>报告员(s) “\'w\\'

Python中的
\uuu str\uuu
\uu repr\uuu
有什么区别?

来自effbot:


\uuuu str\uuuuu
计算对象的“非正式”字符串表示形式。这与
\uuuuu repr\uuuuu
不同,因为它不必是有效的Python表达式:可以使用更方便或简洁的表示形式。”

\uuuu repr\uuuu
:python对象的表示形式通常eval会将其转换回该对象

\uuuu str\uuuuu
:是您认为文本形式的对象

e、 g

>>s=“”w'o“w”“”
>>>报告员(s)
“\'w\\'o”w\'
>>>str(s)
“w”“o”“w”
>>>eval(str(s))==s
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第1行
w'o“w
^
SyntaxError:扫描单引号字符串时下线
>>>评估(报告)=s
真的

除非您特别采取行动以确保其他方面,否则大多数类在以下两方面都没有有用的结果:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 
如您所见,如果覆盖
\uuuuu repr\uuuu
,它也用于
\uuuu str\uuuu
,但反之亦然

需要了解的其他重要花絮:内置容器上的
\uuuuu str\uuuu
对其包含的项目使用
\uuuu repr\uuuu
,而不是
\uuu str\uuuu
。而且,尽管在典型的文档中可以找到关于这个主题的词语,但几乎没有人愿意将对象的
\uuuu repr\uuuu
变成一个字符串,而
eval
可以用来构建一个相等的对象(这太难了,而且不知道相关模块实际上是如何导入的,这实际上是不可能的)


因此,我的建议是:集中精力使
\uuuuu str\uuuuu
具有合理的人类可读性,并尽可能使
\uuuuu repr\uuuuuu
尽可能明确,即使这会干扰模糊的无法实现的目标,即使
\uuuu repr\uuuuuu
的返回值可以作为
\uu eval\uuucode>的输入

我的经验法则:
\uuuu repr\uuu
是给开发者的,
\uu str\uuu
是给客户的。

总结得很好,但令人惊讶的是,太简洁了

首先,让我重申以下要点:

  • 默认的实现是无用的(很难想象有一个不是,但是是的)
  • \uuuu repr\uuuu
    目标是明确无误
  • \uuuu str\uuuu
    目标是可读的
  • 容器的
    \uuuu str\uuuu
    使用包含的对象“
    \uuuuu repr\uuuu
默认实现是无用的

这主要是一个惊喜,因为Python的默认值往往相当有用。但是,在这种情况下,
\uuuu repr\uuu
的默认值如下:

return "%s(%r)" % (self.__class__, self.__dict__)
太危险了(例如,如果对象相互引用,就很容易陷入无限递归)。所以蟒蛇逃走了。请注意,有一个默认值为true:如果定义了
\uuuu repr\uuuu
,而未定义
\uuuu str\uuuu
,则对象的行为将类似于
\uuuuu str\uuu=\uuuuu repr\uu

class Person:
def __init__(self, name, age):
    self.name = name
    self.age = age

def __str__(self):
    print('__str__ called')
    return self.name

p=Person('ali',20)
简单地说,这意味着:几乎您实现的每个对象都应该有一个可用于理解对象的功能性
\uu repr\uu
。实现
\uuuu str\uuuu
是可选的:如果您需要“漂亮打印”功能(例如,由报表生成器使用),请执行此操作

的目标是明确无误

让我直截了当地说出来——我不相信调试器。我真的不知道如何使用任何调试器,也从未认真使用过。此外,我相信调试器的最大缺陷是它们的基本特性——我调试的大多数故障都发生在很久以前,在遥远的银河系中。这意味着我怀着宗教的热情相信伐木。日志记录是任何体面的fire and forget服务器系统的生命线。Python使日志记录变得很容易:使用一些特定于项目的包装器,您所需要的只是一个

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
但是您必须完成最后一步——确保您实现的每个对象都有一个有用的repr,这样这样这样的代码就可以正常工作。这就是为什么会出现“eval”的问题:如果你有足够的信息,那么
eval(repr(c))==c
,这意味着你知道关于
c
的一切。如果这很容易,至少以一种模糊的方式,那么就去做吧。如果没有,请确保您有足够的关于
c
的信息。我通常使用类似eval的格式:
“MyClass(this=%r,that=%r)”%(self.this,self.that)
。这并不意味着您可以实际构造MyClass,或者这些都是正确的构造函数参数,但它是一种有用的形式,可以表示“这就是您需要了解的有关此实例的所有信息”

注意:我使用了上面的
%r
,而不是
%s
。您总是希望在
\uuu repr\uuu
实现中使用
repr()
[或
%r
格式化字符,等价地],否则您将无法实现repr的目标。您希望能够区分
MyClass(3)
MyClass(“3”)

代码的目标是可读性

具体地说,它并不打算明确-注意
str(3)==str(“3”)
。同样,如果您实现一个IP抽象,让它的str看起来像192.168.1.1就可以了。在实现日期/时间抽象时,str可以是“2010/4/12 15:35:22”,等等。目标是以用户而不是程序员希望阅读的方式表示它。切掉无用的数字,假装是其他类-只要它支持可读性,这就是一种改进

容器的
\uuuu str\uuuuuuuuuuuuuuuuuuuu
使用包含对象的
\uuuuuuu repr\uuuuuuuuuu

这似乎令人惊讶,不是吗?它有点小,但是如果它使用他们的
\uuuu str\uuuu
,它的可读性会有多高

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
不太好。具体来说,容器中的字符串很容易干扰其字符串表示。
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
print "[" + ", ".join(l) + "]"
>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'
repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.
def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))
<__main__.Foo object at 0x7f80665abdd0>
import datetime
>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951
>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180
def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s
def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')
def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"
class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'
In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form
In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.
In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)
In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'
In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside
class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr
>>> x, y = 'foo', 123
>>> str(x), str(y)
('foo', '123')
>>> 123
123
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> eval('123')
123
>>> eval('foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'foo' is not defined
>>> repr(x), repr(y)
("'foo'", '123')
>>> 123
123
>>> 'foo'
'foo'
>>> eval('123')
123
>>> eval("'foo'")
'foo'
class Person:
     pass

p=Person()
 <__main__.Person object at 0x7fb2604f03a0>
class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __repr__(self):
        print("__repr__ called")
        return f"Person(name='{self.name}',age={self.age})"

p=Person("ali",20)
 __repr__ called
     Person(name='ali',age=20)
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __repr__(self):
        print('__repr__ called')
        return f"Person(name='{self.name}, age=self.age')"
    
    def __str__(self):
        print('__str__ called')
        return self.name

p=Person("ali",20)
__str__ called
ali
class Person:
def __init__(self, name, age):
    self.name = name
    self.age = age

def __str__(self):
    print('__str__ called')
    return self.name

p=Person('ali',20)
__str__ called
ali