天天看点

python中魔法方法__str__与__repr__的区别

文章目录

      • 0.故事背景
      • 1.__str__ & __repr__ 方法
        • 1.重写__str__
        • 2.重写__repr__
        • 3.重写__repr__ & __str__方法
      • 2.str() & repr() 函数
      • 3.__str__与__repr__的本质区别

0.故事背景

# 以下为交互模式

In [1]: class People: 
   ...:     def __init__(self, name, sex): 
   ...:         self.name = name 
   ...:         self.sex = sex 
   ...:                                                                         

In [2]: p = People('xiaoming', 'male')                                          

In [3]: p                                  	# 直接输入p                                     
Out[3]: <__main__.People at 0x7fd0df745400>




In [4]: print(p)                            # 打印对象p                                   
<__main__.People object at 0x7fd0df745400>

           
  • 两种方式显示出来的信息都是对象所属类的名称以及对象所在的地址,而很多时候这不是我们想要的信息。
  • 此时我们可以通过重写__str__和__repr__方法来定制我们想要的信息。

1.str & repr 方法

  • str_ 和 repr 方法,是自定义类的字符串描述,当我们打印或查看某个对象时,最终看到的结果是这两个方法的返回值。
这两个方法返回的都是字符串,但是什么时候调用__str__?什么时候调用__repr__?我们看下面的例子

1.重写__str__

In [1]: class A: 
   ...:     def __str__(self): 
   ...:         return '__str__' 
   ...:                                                                         

In [2]: a = A()                                                                 

In [3]: a                                	# 直接输入对象a                                       
Out[3]: <__main__.A at 0x7ffb3f2ba048>


In [4]: print(a)                                                                
__str__


           
接输入对象再回车,返回的结果与原来一样;但是打印对象时,触发了__str__方法,显示的对象的属性明显要友好很多!!

2.重写__repr__

In [1]: class B: 
   ...:     def __repr__(self): 
   ...:         return '__repr__' 
   ...:                                                                         

In [2]: b = B()                                                                 

In [3]: b                                                                       
Out[3]: __repr__

In [4]: print(b)                                                                
__repr__


           
通过如上案例得到的结论:
  • 交互模式下,直接输入b,相当于调用了__repr__方法
  • 当打印对象的时候,也调用了__repr__方法

3.重写__repr__ & __str__方法

In [1]: class C: 
   ...:     def __str__(self): 
   ...:         return '__str__' 
   ...:     def __repr__(self): 
   ...:         return '__repr__' 
   ...:                                                                         

In [2]: c = C()                                                                 

In [3]: c                                                                       
Out[3]: __repr__

In [4]: print(c)                                                                
__str__


           
如上得到结论:
  • 交互模式下,直接输入对象c,调用的是__repr__方法
  • 打印对象的时候,直接调用如果有__str__方法,则直接调用__str__方法,如果没有则调用__repr__方法,如果这两个方法都没有,则正常打印类的内存地址信息

2.str() & repr() 函数

str()默认触发__str__方法,repr()默认触发__repr__方法,触发的机制与上述一样;另外,列表、字典等容器总是会触发__repr__方法,代码示例如下:
# 类中只重写了__str__方法
In [5]: str(a)                                                                  
Out[5]: '__str__'

In [6]: repr(a)                                                                 
Out[6]: '<__main__.A object at 0x7ffb3f2ba048>'

# 类中只重写了__repr__方法 
In [5]: str(b)                                                                  
Out[5]: '__repr__'

In [6]: repr(b)                                                                 
Out[6]: '__repr__'

# 类中重写了__str__与__repr__方法 
In [5]: str(c)                                                                 
Out[5]: '__str__'

In [6]: repr(c)                                                                
Out[6]: '__repr__'

# 列表、字典等容器总是会触发__repr__方法  
In [53]: print([a])                                                             
[<__main__.A object at 0x7ffb3f2ba048>]                                                         
                                                              
In [7]: str([c])                                                               
Out[7]: '[__repr__]'

In [8]: repr([c])                                                              
Out[8]: '[__repr__]'

In [9]: [c]                                                                    
Out[9]: [__repr__]

In [10]: print([c])                                                             
[__repr__]


           

3.__str__与__repr__的本质区别

那__str__与__repr__的本质区别到底是什么呢? 先看官方描述
  • str: Called by str(object) and the built-in functions format() and print() to compute the “informal” or nicely printable string representation of an object.
  • repr: Called by the repr() built-in function to compute the “official” string representation of an object. This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.
总结一下:
  • __str__是一个对象的非正式的、易于阅读的字符串描述,当类str实例化( str(object) )时会被调用,以及会被内置函数format()和print()调用;
  • __repr__是一个对象的官方的字符串描述,会被内置函数repr()方法调用,它的描述必须是信息丰富的和明确的。也就是说__str__返回的结果可读性强,__repr__返回的结果更加准确。再看一个例子
In [1]: import datetime                                                         

In [2]: d = datetime.datetime.now()                                             

In [3]: str(d)                                                                  
Out[3]: '2019-08-24 08:12:17.942242'    # 可读性强

In [4]: repr(d)                                                                 
Out[4]: 'datetime.datetime(2019, 8, 24, 8, 12, 17, 942242)'    # 信息更加丰富和准确


           

总结:

  • 在自定义类中,可以通过重写__str__和__repr__方法来定制类对象到字符串的转化。
  • 一般情况下,推荐至少添加一个 repr 方法来定制对象到字符串的自定义转化,str 是可选的。因为默认情况下,在需要却找不到 str 方法的时候,会自动调用 repr 方法。
  • __str__方法的目标在于可读性,__repr__方法的目标在于准确性。
文章来源:https://www.cnblogs.com/miaoning/p/11399575.html