一、思考

当我们在Python中定义一个类的时候,如果我们通过print打印这个类的实例化对象,或者我们直接输入这个类实例化对象会返回怎么样的结果,如下代码:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> tom = People("Tom", 23)
>>> print(tom)
<__main__.People object at 0x00000000027A7160>
>>> tom
<__main__.People object at 0x00000000027A7160>
>>>

默认情况下,你得到的是一个字符串,其中包含类名和对象实例的id(这是CPython中对象的内存地址),其实有更加Pythonic的方式去控制不同情况下将对象进行转换为字符串,也就是控制其显示的结果内容。 我们把上面的代码进行更改的内容如下:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> tom
<__main__.People object at 0x00000000021B7208>
>>>

str 是python的内置方法,并且当你在尝试去吧一个对象转换为一个字符串的时候怎么调用这个str方法,如我们进行如下操作时:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
<__main__.People object at 0x00000000021E7208>
>>>

二、__str__ vs __repr__

在上面的代码中我们添加了str_方法之后,当我们将对象转换为字符串的时候都会调用str方法,并得到我们自己定义的内容,但是并没有影响到我们在python交互模式下直接输入对象的返回内容。其实
repr 和 str 其实是非常类似的,只不过用的场景不同,将上面的代码进行调整:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
... def __repr__(self):
... return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

其实这里也就验证了,在Python的交互模式下,检查一个对象,其实就是在调用对象的repr方法,还有一个你可能没有发现的地方就是当你在list,dict等容器中存储对象的时候,我们打印看到的都是repr的内容,我们把上面的tom存到列表里, 然后打印查看如下:

>>> print([tom])
[__repr__: people name is Tom]
>>>

为了验证我们到底应该怎么用这两个方法,毕竟这两个方法的作用还是非常类似的,我们可以通过Python标准库来验证一下,跟着标准库走总不会有错

>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2019, 3, 5)
>>> str(today)
'2019-03-05'
>>> repr(today)
'datetime.date(2019, 3, 5)'
>>>

从这个Python标准库的用法,我们也能非常好的理解str方法其实就是为了返回一个人们容易理解的字符串类型的结果,而repr方法更偏向于程序员方便去调试,能从结果中看到更加有用的信息,它甚至包括完整的模块和类

三、Why Every Class Needs a repr

我们先看一下我们将我们上面代码的str方法去掉之后的结果:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... # def __str__(self):
... # return f"people name is {self.name}"
... def __repr__(self):
... return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
__repr__: people name is Tom
>>> str(tom)
'__repr__: people name is Tom'
>>> '{}'.format(tom)
'__repr__: people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

从这里我们发现当当你把对象进行字符串转换的时候,就会先去找str方法,如果没有则再去找repr方法执行
所以还是建议在自己定义的类中都至少有一个repr方法,这样不管在上面情况下,你都能有一个对你来说有用的字符串返回结果,而不再是一个干巴巴的内存地址,所以在最后我们规范一下我们写一个Python类时的代码:

class People(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'people name is {self.name}'
def __repr__(self):
return (f'{self.__class__.__name__}('
f'{self.name!r}, {self.age!r})')

在最后的repr的返回中我们用了!r 这个意味着我们要的repr(self.name) repr(self.age)而不是要str(self.name) str(self.age)的返回结果

Python Every Class Needs a __repr__的更多相关文章

  1. python中的__str__和__repr__方法

    如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class A(object): def __init__(self,name,age): self.name=name se ...

  2. 第8.15节 Python重写自定义类的__repr__方法

    一. 引言 前面两节分别介绍了Python类中的__str__和__repr__方法的作用和语法,所有新式类都支持这两个方法,因为object类实现了这两个方法,但实际上各位开发者在自定义类的过程中, ...

  3. Python中的魔法函数__repr__和__str__的实质性区别

    str 和 repr 方法:是自定义类的字符串描述,这两种都是比较 Pythonic 的方式去控制对象转化为字符串的方式. 调用这两个方法,返回的都是字符串.但是这两个方法又有一些区别 ** 1 两种 ...

  4. python 中的__str__ 和__repr__方法

    看下面的例子就明白了 class Test(object): def __init__(self, value='hello, world!'): self.data = value >> ...

  5. python 的特殊方法 __str__和__repr__

    __str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, name, ...

  6. 浅谈python中__str__和__repr__的区别

    很多时候我们在创建一个类的时候,在终端打印类或者查看的时候一般都不会得到一个太满意的结果 class T: def __init__(self): self.color="red" ...

  7. Python中自定义类如果重写了__repr__方法为什么会影响到str的输出?

    这是因为Python3中,str的输出是调用类的实例方法__str__来输出,如果__str__方法没有重写,则自动继承object类的__str__方法,而object类的__str__方法是调用_ ...

  8. 利用Python特殊变量__dict__快速实现__repr__的一种方法

    在<第8.15节 Python重写自定义类的__repr__方法>.<Python中repr(变量)和str(变量)的返回值有什么区别和联系>.<第8.13节 Pytho ...

  9. Python基础学习笔记FromImooc.com

    1.list L = ['a','a','a','a','a','a3'] L[0] = a L[-1] = a3   添加新元素 L.append('paul') L.insert(-1,'Paul ...

随机推荐

  1. 秒懂HTTPS

    http和https HTTP:超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议.HTTP是万维网的数 ...

  2. SpringCloud Gateway入门

    本文是介绍一下SpringCloud Gateway简单路由转发使用. SpringCloud Gateway简介 SpringCloud是基于Spring Framework 5,Project R ...

  3. MacOs brew 命令行安装常见工具

    brew类似ubuntu系统下的apt-get的功能 安装方法:  在Mac中打开Termal:  输入命令: ruby -e "$(curl -fsSL https://raw.githu ...

  4. [OC] 使用 cocoaPods 导入 AFNetworking

    AFNetworking的GitHub地址: https://github.com/AFNetworking/AFNetworking 假设我们建立了一个叫做AFNWlearning的工程. 1.打开 ...

  5. Codeforces.209C.Trails and Glades(构造 欧拉回路)

    题目链接 \(Description\) 给定一张\(n\)个点\(m\)条边的无向图,允许有自环重边.求最少加多少条边后,其存在从\(1\)出发最后回到\(1\)的欧拉回路. 注意,欧拉回路是指要经 ...

  6. BZOJ.3165.[HEOI2013]Segment(李超线段树)

    BZOJ 洛谷 对于线段,依旧是存斜率即可. 表示精度误差一点都不需要管啊/托腮 就我一个人看成了mod(10^9+1)吗.. //4248kb 892ms #include <cstdio&g ...

  7. me 云面试

    元祖的特点: 1.元组内的元素,不可以增加,删除,只能访问,这个是元祖的特性,比较安全.类似于字符串.但是我们可以对整个元祖进行删除.使用del内置函数 2.当元祖内只有一个元素的时候,需要加逗号消除 ...

  8. Charles——前端必备模拟后端数据

    Charles--前端必备模拟后端数据 现在都是前后端分离开发了,前端开发者经常会遇到一个问题如何模拟后端数据来进行开发调试,在这里给大家介绍一个前端神器--Charles. 安装 安装就不赘述了,直 ...

  9. PHP判断iPhone、iPad、Android、PC设备的方法

    因为工作需要我们需要知道是什么样了用户访问了我网站了,现在的移动设备种类多了,下面我们一起来看小编整理的一段php判断iPhone.iPad.Android.PC设备的例子. 注意:本代码的PC系统为 ...

  10. 一个label两种颜色,一个label两种字体

    -(void)addLabel{ UILabel *label = [[UILabel alloc]init]; label.backgroundColor = [UIColor grayColor] ...