吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1195|回复: 1
收起左侧

[Python 转载] [笔记] __str__和__repr__学习笔记

[复制链接]
the_stars 发表于 2020-9-1 19:56

今天突发奇想打算把所知道的各种魔法方法, 就是__x__方法记录一下, 以后可以拿来看, 也可以和大家一起讨论.\

这次打算记录两个简单的__方法, 分别是__str__和__repr__

前言

Python中, print语句打印一个对象, 比如

class Test(object):
    pass

print(Test)
print(Test())
<class '__main__.Test'>
<__main__.Test object at 0x00000178E84F8460>

打印的和我们正常见到的没什么区别, 但是却得不到任何信息, 打印一个对象, 很多时候我们希望打印的时候可以告诉我们一些信息, 比如一个列表, 我们打印它, 输出的

>>> print([1, 2, 3, 4])
[1, 2, 3, 4]

而不是那么<list object at 0x00000178E84F8460>, 因为我们打印列表的需求就是想看到列表中的内容, 以便我们进行调试, 看看是不是符合我们的预期等等, 如果打印一个<list object at 0x00000178E84F8460>, 那我们什么都得不到, 总不能每个地方都进行for循环打印出来吧. 显然太麻烦了. 那么如何自定义一个类的打印, 就是与__str____repr__有关了.

__str__

我们可以在一个类中定义__str__方法, 这个方法返回的必须是一个字符串, 当我们调用print(xxx)时, 就会调用xxx的__str__方法, 打印出这个方法返回的字符串.

class Point(object):
        def __init__(self, x=0, y=0):
                self.x = x
                self.y = y

        def __str__(self):
                return "<Point (%d, %d)>" % (self.x, self.y)

p1 = Point(1, 2)
print(p1)

打印结果

<Point (1, 2)>

Point这个类就是用来表示一个点的, 有两个属性x, y代表x和y轴的坐标, 我们如果要打印一个点, 自然希望把他的坐标打印出来, 而不是什么 <Point object in 0xxxxx>, 因此就可以通过重写__str__方法,  来返回我们希望看到的字符串, 在返回值里面我们格式化了它的x和y.

这里拓展一下, 我们如果没定义__str__, 打印对象也会有字符串信息, 那么是不是就代表着调用了父类的__str__呢? 如果是, 那么父类的__str__应该是返回的什么呢? 我们打印一个没定义__str__的时候, 返回的是这种形式<__main__.Test object at 0x000002D075A88460>, 那么我们猜测, object的__str__应该是这样的, 这里的self.__class__等价type(self)

class object:
    ...

    def __str__(self):
        return "<__main__.%s object at %s>" % (self.__class__.__name__, hex(id(self)))

    ...

这样子我们打印任何一个对象, 如果没重写__str__方法都将会打印出<__main__.xx object at xx>, 知道这个就差不多了, 不过补充一下的是, 并不是每一个打印出来前面都是<__main__ xxxx>, 更准确的应该是这样的

        return "<%s.%s object at %s>" % (self.__module__, self.__class__.__name__, hex(id(self)))

了解即可, 那个__module__只是它在的模块, 当前运行的就是__main__.  

__str__真的只是打印的时候才会被调用么?

其实__str__的真正含义就是怎么把一个对象看成一个字符串, 定义了这个方法, 就自定义了怎么去把它看成字符串, 我们打印一个东西, 比如print(xxx)其实是打印xxx被看成的字符串, 可以理解为内部会做这样的转换

print(xxx) => print(str(xxx)), 先获取字符串信息, 在把那个字符串信息打印出来, 因此这里的__str__其实就是自定义的类如何用字符串解释. 因此我们调用str(xxx)其实就是调用了 xxx.__str__()创建一个字符串实例.

class Point(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return "<Point (%d, %d)>" % (self.x, self.y)

s = str(Point(1, 2))

s = s + "123"

print(s)

输出

<Point (1, 2)>123

如果以后发现某一些魔法方法, __xxx__, 然后又发现一些内置函数或者类xxx, 出了开头结尾两个__其余的名字是一样的

比如__str__方法str类, __repr__repr函数, __iter__方法iter函数, 那么一般情况(注意是一般情况),

str(xxx)返回的是xxx.__str__(),

iter(xxx)返回的是xxx.__iter__(),

int(xxx)返回的是xxx.__int__(),

len(xxx)返回的是xxx.__len__().

__repr__

如果理解了__str__, __repr__理解起来会简单很多. __repr__返回的也是一个字符串, 也用来提供信息, 不过这个提供有点特别, 它是在交互环境直接回车进行提供的. 我们首先运行python的交互环境, 在cmd的输入python

Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

就会进入交互环境, 我们不再用编辑器来进行代码编辑了, 而是一步一步的执行, 下面我们运行

>>> a = 1
>>> a
1
>>>

注意第二行, 只有一个a, 然后下面发现1被输出了, 我们并没有执行print语句, 如果这个代码在ide或者编辑器中写完了, 保存后python xxx.py运行, 它是不会打印的, 只有在控制台中(交互环境), 输入一个变量, 然后回车, 才会打印它的信息.  这个时候打印的信息, 就是那个类的__repr__返回的字符串, 而不再是__str__返回的字符串了.

>>> class Test(object):
...     def __str__(self):
...         return "__str__"
...     
...     def __repr__(self):
...         return "__repr__"
...     
...     
>>> Test()
__repr__
>>> print(Test())
__str__
>>>

那么联系str(xxx)可以想到, 在控制台中, 输入一个变量xxx按回车, 其实可以看成输出repr(xxx)或者xxx.__repr__()返回的字符串.

这里拓展一下, 如果某一个类定义了__repr__方法, 却没有定义__str__方法, 当调用str(xxx)时, 找不到__str__, 会调用这个类的__repr__方法来进行打印.

class Point(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return "__repr__"

print(Point())

输出

__repr__

到这里就差不多完了, 下面记录一下与这个有关的东西, 与这次笔记关系不是那么大.

关于字符串格式化

class Point(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __str__(self):
        return "__str__"

    def __repr__(self):
        return "__repr__"

t = Point()

print(f"{t!s} \n{t!r}")
print("%s \n%r" % (t, t))

输出

__str__ 
__repr__
__str__ 
__repr__

s格式化的意思是返回xxx.__str__的字符串信息, r格式化返回的是xxx.__repr__.

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
Zeaf + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

大兵马元帅 发表于 2020-9-1 22:37
一开始学了,后来放弃了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 01:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表