ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

__repr__和__str__的区别, __repr__是个机器看的, 一般是可以eval的,类名(参数)字符串, __str__是给人看的, 字符串,优先调用

2022-06-11 11:34:25  阅读:96  来源: 互联网

标签:__ 调用 self repr str print


class MyNumber:
    def __init__(self, value):
        self.data = value

    def __str__(self):
        print('正在调用__str__方法,转换为普通字符串')
        s = '自定义数据%d' % self.data
        return s

    def __repr__(self):
        print('正在调用__repr__方法,转换为普通字符串')
        s = 'MyNumber(%d)' % self.data
        return s

n1 = MyNumber(100)
print(n1)
print(str(n1))
print(repr(n1))

输出:

正在调用__str__方法,转换为普通字符串
自定义数据100
正在调用__str__方法,转换为普通字符串
自定义数据100
正在调用__repr__方法,转换为普通字符串
MyNumber(100)
class MyInteger:
    def __init__(self, v):
        self.data = v

    def __repr__(self):
        print('执行__repr__方法')
        return 'MyInteger(%d)' % self.data

    def __abs__(self):
        '''此方法用于制定abs(obj)函数取值时返回的结果'''
        print('执行__abs__方法')
        if self.data < 0:
            return MyInteger(-self.data)  # 用-self.data创建一个新的对象返回回去
        return MyInteger(-self.data)
        return MyInteger(-self.data)

i1 = MyInteger(-100)
print(i1)  # 等同与print(str(i1))
n = abs(i1)
print(n)
'''
输出:

执行__repr__方法
MyInteger(-100)
执行__abs__方法
执行__repr__方法
MyInteger(100


这一段程序比较有意思,先来配合第一段程序来总结下str和repr的调用规则.
    调用 print(i1)  (#等同与print(str(i1)))的时候,解释器第一个寻找的就是i1这个类的方法里面有没有重新定义str,
    如果没有,那么它第二步会去寻找这个类里面有没有重新定义repr,    如果有则会用类方法的repr,如果还没有,那么解释器会找这个类的上一层父类,
    按同样的规则进行寻找,直到最后找到了object,然后用object的str方法,将该对象的内容转成字符串,最后输出到终端.

    调用print(repr(i1))的时候就不一样了,repr只会调用repr方法,当自定义的类中没有重写repr方法的时候,它会直接找上一级的父类中有没有repr方法,
    而不会考虑调用str方法.

    总的来说,repr方法比较傲娇,而str方法就比较随意,所以repr的用法就会像这一段程序一样,当我要输出一个需要自己加工的数据的时候,
    用object的str和repr显然不够,那么就需要在自己的类中重新写一个repr的方法,这样,调用print(XXX)的时候,这个类里面的repr方法就会被调用,
    这段程序里面,repr调用的意义就是输出了一个段字符串用做提示,这一是一般比较常见的用法.

    最后再来总结一些东西,除了顺序之外还有一些细节.
        1.几乎所有的函数重构会遵循一些返回值规则,str和repr也不例外,自己重构这个函数的时候写的返回值必须是字符串类型,
        这个规则被写在了解释器的骨子里,试想下,object里定义这两个东西就是为了输出字符串给人或机器看, ,
        解释器也会很苦恼怎么把int的值显示在终端上,干脆就报错了: TypeError: __str__ returned non-string (type int).
        
        2.所谓给人看和给机器看的意思最直观的就是用eval函数进行测试,eval函数里是需要一个表达式,经过测试就能明白,
        str返回的是个字符串,而repr返回一个能代表此对象的表达式字符串,这个表达式会被eval翻译,结果就是调用repr时传入的对象,
        eval(repr(obj))=obj.而str这么做就会报错.
        
        3.以前经常会有'hello %s'%word  一类的写法,这里%s就是代表了str的类型,其实repr类型对应的是%r,但是都用%s貌似也不会出错,
        不过还是区分一下,显得更专业一些.

        4.一个小细节,算是比较容易出问题的细节,以第二段程序为例,如果我把print(i1)写成print(i1.data)会怎么样,
        结果是会直接输出这个实例的属性的值,而且不会调用这个类里面的str和repr方法,因为print里面放的不是一个实例对象,
        而是该实例的一个属性,所以解释器会直接调用object里面的str,将值转成字符串并输出到了终端,所以一般自己写的类里面重构的repr,
        一般都是用来自定义的去描述一个实例对象的,如果需要带上实例属性,那就像这一段程序一样,在返回的时候把实例属性插进字符串里面好了.
        '''

参考自: https://blog.csdn.net/weixin_30650859/article/details/98143348

标签:__,调用,self,repr,str,print
来源: https://www.cnblogs.com/heris/p/16365533.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有