最近一下子学了很多的知识点,导致我有点没反应过来,粗略的在草稿纸记了点自己的想法,趁休息的时间将它敲到博客里面去,免得丢失,这一篇写的挺废话的,有点啰嗦,本篇的重点是第二段程序后开始的总结和后面的几个细节问题。

关于__repr__和__str__这连个东西,我最开始就感觉有点难以理解,百度来的东西看了很多遍,定义都能背下来了,随口一说就是一个给机器看的一个给人看的,但是感觉只理解了最表面,当然不是网上大佬给的答案不够好,而是某些东西还是需要自己去思考,然后有一番自己的理解,然后写点程序验证下,这才是最好的。

首先,我把这两个的东西对实例对象的操作称为“渲染”,可能不太准确,但是我觉这么叫方便我去理解。

第一步先写一个简单的类:MyNumber,先来理解下在输出实例的时候,str和repr的操作方式

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

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

return s

n1 = MyNumber(100),

这个类里面除了init方法还有str和repr,首先,我们在用print输出任何东西的时候,都会有一个渲染步骤,而且默认的就是用str进行渲染,因为任何一样东西都可以看做一个对象,那么它必有一个类型,如果它的类里面没有定义str和repr也没关系,object里面定义了str和repr,object是一切类的父类,所以输出的对象一定会是渲染过的。这个类里面自己写了str和repr,它覆盖了object里面的str和repr,相当于print的重定向。

接下来就是输出了,print(n1)和print(str(n1))是一样的效果的,因为他们都会调用类里面的str方法,其中print(n1)是默认调用str的。print(repr(n1))的结果就不一样了,它会调用这个类里面的repr方法。

接下来再弄一段来记下repr的用法和两者的区别。

class MyInteger:
        def __init__(self,v):
            self.data = v
        def __repr__(self):
            return 'MyInteger(%d)'%self.data
        def __abs__(self): 
        '''此方法用于制定abs(obj)函数取值时返回的结果'''
            if self.data < 0:
                return MyInteger(-self.data) #用-self.data创建一个新的对象返回回去
            return MyInteger(-self.data)
    i1 = MyInteger(-100)
    print(i1)  #等同与print(str(i1))
    n = abs(i1)

print(n)

这一段程序比较有意思,先来配合第一段程序来总结下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型的值,解释器也会很苦恼怎么把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,一般都是用来自定义的去描述一个实例对象的,如果需要带上实例属性,那就像这一段程序一样,在返回的时候把实例属性插进字符串里面好了。
---------------------
作者:汐陌夏初
来源:CSDN
原文:https://blog.csdn.net/qq_36272641/article/details/80875222
版权声明:本文为博主原创文章,转载请附上博文链接!

__rept__和__str__的更多相关文章

  1. python 的特殊方法 __str__和__repr__

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

  2. python的class的__str__()和__repr__()函数

    repr(object) 返回一个可以用来表示对象的可打印字符串首先,尝试生成这样一个字符串,将其传给 eval()可重新生成同样的对象 否则,生成用尖括号包住的字符串,包含类型名和额外的信息(比如地 ...

  3. python __str__ & __repr__ & __cmp__

    For ( __str__ ),we going to see a example ... and find who is working for ... #!/usr/bin/python clas ...

  4. __str__

    __str__是被print函数调用的,一般都是return一个什么东西.这个东西应该是以字符串的形式表现的.如果不是要用str()函数转换.当你打印一个类的时候,那么print首先调用的就是类里面的 ...

  5. python面对对象编程------4:类基本的特殊方法__str__,__repr__,__hash__,__new__,__bool__,6大比较方法

    一:string相关:__str__(),__repr__(),__format__() str方法更面向人类阅读,print()使用的就是str repr方法更面对python,目标是希望生成一个放 ...

  6. Django rest framework:__str__ returned non-string (type NoneType) 真正原因

    出错原因: 用户表是Django中核心的表,当这个表类字段中有一个这样的函数 def __str__(self): return self.name 在Django用户表设计时候有个字段容易犯这个失误 ...

  7. python __str__ 和__repr__方法

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

  8. python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

    一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...

  9. __str__与__repr__

    在讲解之前,我们先来了解下str和repr的区别:两者都是用来将数字,列表等类型的数据转化为字符串的形式.不同之处在于str更加类似于C语言中使用printf输出的内容,而repr输出的内容会直接将变 ...

随机推荐

  1. 【LeetCode】384. Shuffle an Array 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 库函数 Fisher–Yates 洗牌 水塘抽样 日 ...

  2. 【LeetCode】5. Longest Palindromic Substring 最长回文子串

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...

  3. 使用.NET 6开发TodoList应用(10)——实现DELETE请求以及HTTP请求幂等性

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 先说明一下关于原本想要去更新的PATCH请求的文章,从目前试验的情况来看,如果是按照.NET 6的项目结构(即只使用一个Pro ...

  4. Roslyn+T4+EnvDTE项目完全自动化(3) ——生成c++代码

    C++语法复杂,写一个示例通过T4可生成c++代码 需求:数据库,生成c++增,删,改,查代码 数据生成c++类,包含所有字段 自动识别数据的主键Key 查询生成赋值类字段,类型转换 通过类自动生成s ...

  5. solr - 安装ik中文分词 和初始化富文本检索

    1.下载安装包 https://repo1.maven.org/maven2/org/apache/solr/solr-dataimporthandler/7.4.0/solr-dataimporth ...

  6. 访问 远程 tomcat 的管理页面 /manager/html 提示 403 的具体解决操作

    1.前言 我在阿里云服务器放了个tomcat ,启动后 ,访问 /manager/html提示403无权访问 原因是 tomcat默认仅仅允许本地的浏览器访问,有ip限制 需要将ip限制去除 顺便把账 ...

  7. spring boot -- 配置文件application.properties 换成 application.yml

    1.前言 其实两种配置文件在spring boot 的作用一样,只是写法不同 ,yml 可以写的内容更少 ,以树结构 书写内容,看起来很清晰, 但是 如果 项目配置文件设置为 既有properties ...

  8. Python实战案例系列(一)

    本节目录 烟草扫码数据统计 奖学金统计 实战一.烟草扫码数据统计 1. 需求分析 根据扫码信息在数据库文件中匹配相应规格详细信息,并进行个数统计 条码库.xls 扫码.xlsx 一个条码对应多个规格名 ...

  9. SSM简单实现文件上传和下载

    一.配置spring-mvc <!-- 配置多媒体文件解析器 --> <bean id="multipartResolver" class="org.s ...

  10. SparkSQL学习笔记

    概述 冠状病毒来临,宅在家中给国家做贡献之际,写一篇随笔记录SparkSQL的学习笔记,目的有二,一是记录整理之前的知识作为备忘录,二是分享技术,大家共同进步,有问题也希望大家不吝赐教.总体而言,大数 ...