zl程序教程

您现在的位置是:首页 >  后端

当前栏目

《Python面向对象编程指南》——第2章 与Python无缝集成——基本特殊方法 2.1 __repr__()和__str__()方法

Python集成方法 指南 基本 2.1 __ 特殊
2023-09-11 14:17:36 时间

本节书摘来自异步社区《Python面向对象编程指南》一书中的第2章,第2.1节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

第2章 与Python无缝集成——基本特殊方法

Python中有一些特殊方法,它们允许我们的类和Python更好地集成。在标准库参考(Standard Library Reference)中,它们被称为基本特殊方法,是与Python的其他特性无缝集成的基础。

例如,我们用字符串来表示一个对象的值。Object基类包含了__repr__()和__str__()的默认实现,它们提供了一个对象的字符串描述。遗憾的是,这些默认的实现不够详细。我们几乎总会想重写它们中的一个或两个。我们还会介绍__format__(),它更加复杂一些,但是和上面两个方法的作用相同。

我们还会介绍其他的转换方法,尤其是__hash__()、__bool__()和__bytes__()。这些方法可以把一个对象转换成一个数字、一个布尔值或者一串字节。例如,当我们实现了__bool__(),我们就可以像下面这样在if语句中使用我们的对象:if someobject:。

接下来,我们会介绍实现了比较运算符的几个特殊方法:__lt__()、__le__()、__eq__()、__ne__()、__gt__()和__ge__()。

当我们定义一个类时,几乎总是需要使用这些基本的特殊方法。

我们会在最后介绍__new__()和__del__(),因为它们的使用更加复杂,而且相比于其他的特殊方法,我们并不会经常使用它们。

我们会详细地介绍如何用这些特殊方法来扩展一个简单类。我们需要了解从object继承而来的默认行为,这样,我们才能理解应该在什么时候使用重写,以及如何使用它。

2.1 __repr__()和__str__()方法

对于一个对象,Python提供了两种字符串表示。它们和内建函数repr()、str()、print()及string.format()的功能是一致的。

通常,str()方法表示的对象对用户更加友好。这个方法是由对象的__str__方法实现的。 repr()方法的表示通常会更加技术化,甚至有可能是一个完整的Python表达式。文档中写道:

对于大多数类型,这个方法会尝试给出和调用eval()一样的结果。

这个方法是由__repr__()方法实现的。

print()函数会调用str()来生成要输出的对象。 字符串的format()函数也可以使用这些方法。当我们使用{!r}或者{!s}格式时,我们实际上分别调用了__repr__()或者__str__()方法。

下面我们先来看一下这些方法的默认实现。

下面是一个很简单的类。

class Card:

 insure= False

 def __init__( self, rank, suit ):

 self.suit= suit

 self.rank= rank

 self.hard, self.soft = self._points()

class NumberCard( Card ):

 def _points( self ):

 return int(self.rank), int(self.rank)

我们定义了两个简单类,每个类包含4个属性。

下面是在命令行中使用NumberCard类的结果。

 x=NumberCard( 2, )

 str(x)

 __main__.NumberCard object at 0x1013ea610 

 repr(x)

 __main__.NumberCard object at 0x1013ea610 

 print(x)

 __main__.NumberCard object at 0x1013ea610 

可以看到,__str__()和__repr__()的默认实现并不能提供非常有用的信息。

在以下两种情况下,我们可以考虑重写__str__()和__repr__()。

非集合对象:一个不包括任何其他集合对象的“简单”对象,这类对象的格式化通常不会特别复杂。 集合对象:一个包含集合的对象,这类对象的格式化会更为复杂。 2.1.1 非集合对象的__str__()和__repr__()

正如我们在前面看到的,__str__()和__repr__()并没有提供有用的信息,我们几乎总是需要重载它们。下面是当对象中不包括集合时我们可以使用的一种方法。这些方法是我们前面定义的Card类的方法。

 def __repr__( self ):

 return "{__class__.__name__}(suit={suit!r}, rank={rank!r})".

format(

 __class__=self.__class__, **self.__dict__)

 def __str__( self ):

 return "{rank}{suit}".format(**self.__dict__)

这两个方法依赖于如何将对象的内部实例变量__dict__传递给format()函数。这种方式对于使用__slots__的函数并不合适,通常来说,这些都是不可变的对象。在格式规范中使用名字可以让格式化更加可读,不过它也让格式化模板更长。以__repr__()为例,我们传递了__dict__和__class__作为format()函数的参数。

格式化模板使用了两种格式化的规范。

{__class__.__name__}模板,有时候也被写成{__class__.__name__!s},提供了类名的简单字符串表示。 {suit!r}和{rank!r}模板,它们都使用了!r格式规范来给repr()方法提供属性值。

以__str__()为例,我们只传递了对象的__dict__,而内部则是隐式使用了{!s}格式规范来提供str()方法的属性值。

2.1.2 集合中的__str__()和__repr__()

涉及集合的时候,我们需要格式化集合中的单个对象以及这些对象的整体容器。下面是一个包含__str__()和__repr__()的简单集合。

class Hand:

 def __init__( self, dealer_card, *cards ):

 self.dealer_card= dealer_card

 self.cards= list(cards)

 def __str__( self ):

 return ", ".join( map(str, self.cards) )

 def __repr__( self ):

 return "{__class__.__name__}({dealer_card!r}, {_cards_str})".

format(

 __class__=self.__class__,

 _cards_str=", ".join( map(repr, self.cards) ),

 **self.__dict__ )

__str__()方法很简单。

1.调用map函数对集合中的每个对象使用str()方法,这会基于返回的字符串集合创建一个迭代器。

2.用",".join()将所有对象的字符串表示连接成一个长字符串。

__repr__()方法更加复杂。

1.调用map函数对集合中的每个对象应用repr()方法,这会基于返回的结果集创建一个迭代器。

2.使用".".join()连接所有对象的字符串表示。

3.用__class__、集合字符串和__dict__中的不同属性创建一些关键字。我们将集合字符串命名为_card_str,这样就不会和现有的属性冲突。

4.用"{__class__.__name__}({dealer_card!r}, {_cards_str})".format()来连接类名和之前连接的对象字符串。我们使用!r格式化来保证属性也会使用repr()来转换。

在一些情况下,我们可以优化这个过程,让它更加简单。在格式化中使用位置参数可以在一定程度上简化模板字符串。


Python面向对象编程-进阶篇 面向对象三大特性:封装、继承、多态,面向对象中的变量:类变量、成员变量、局部变量,类中的私有方法和私有属性,类的三类方法:实例方法、类方法、静态方法。
Python面向对象编程之外部访问 回顾一下,“对象”本质是一个代码封装思想,在编写的时候考虑尽可能完善的功能,后期直接调用即可,无需明确每一步是如何实现的,隐藏了可能重复出现的复杂逻辑,让使用者把精力放在新的探索和改进上。 但是,我们在调用的时候有没有可能将某个对象的属性修改了呢? 我们今天就一起来看看面向对象编程中对象class的外部访问——
python的面向对象编程初步 与JavaScript是否面向对象具有争议不同,python从设计之初就已经被构思成了一门面向对象的语言。大家或多或少听说过python“一切皆对象”的说法,不论理解与否,至少可以看出对象的概念在python中尤为重要 本期我们就来一起看看python的“对象”到底指的是什么,尝试理解面向编程。这对之后学习类似的面向对象编程也会有很大的帮助。
Python面向对象编程之“类和实例” 作为面向对象的语言,python自然具有“对象”的概念,并且还非常重要。 在面向对象中,“类和实例”这两个的概念是非常重要的。熟练运用好类以及实例,会让python工程师事半功倍。
Python特殊方法 Python特殊方法自制脑图 特殊方法也称为魔术方法,特殊方法都是使用_开头和结尾的;特殊方法一般不需要我们手动调用,需要在一些特殊情况下自动执行。
异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。