《Python面向对象编程指南》——1.6 在每个子类中实现__init()__方法

简介:

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

1.6 在每个子类中实现__init()__方法

正如介绍工厂函数那样,这里我们也先看一些Card类的设计实例。我们可以考虑重构rank数值转换的代码,并把这个功能加在Card类上。这样就可以把初始化的工作分发到每个子类来完成。

这通常需要在基类中完成一些公共的初始化逻辑,子类中完成各自特殊的初始化逻辑。我们需要遵守不要重复自己(Don't Repeat Yourself,DRY)的原则来防止子类中的代码重复。

以下代码演示了如何把初始化职责分发到各自的子类中。

class Card:
  pass
class NumberCard( Card ):
  def __init__( self, rank, suit ):
    self.suit= suit
    self.rank= str(rank)
    self.hard = self.soft = rank
class AceCard( Card ):
  def __init__( self, rank, suit ):
    self.suit= suit
    self.rank= "A"
    self.hard, self.soft = 1, 11
class FaceCard( Card ):
  def __init__( self, rank, suit ):
    self.suit= suit
    self.rank= {11: 'J', 12: 'Q', 13: 'K' }[rank]
    self.hard = self.soft = 1

上例代码是多态的实现,由于缺乏公共初始化函数,导致了一些不受欢迎的重复代码。以上代码的主要重复部分是对suit的赋值。这部分代码放在基类中显然比较合适。我们可以在子类中显式调用基类的__init()__方法。

以下代码演示了如何把__init()__方法提到基类Card中实现的过程,然后在子类中可以重用基类的实现。

class Card:
  def __init__( self, rank, suit, hard, soft ):
    self.rank= rank
    self.suit= suit
    self.hard= hard
    self.soft= soft
class NumberCard( Card ):
  def __init__( self, rank, suit ):
    super().__init__( str(rank), suit, rank, rank )
class AceCard( Card ):
  def __init__( self, rank, suit ):
    super().__init__( "A", suit, 1, 11 )
class FaceCard( Card ):
  def __init__( self, rank, suit ):
    super().__init__( {11: 'J', 12: 'Q', 13: 'K' }[rank], suit, 
10, 10 )

我们在子类和基类中都提供了__init()__方法的实现,这样会在一定程度上简化工厂函数的逻辑,如下面代码段所示。

def card10( rank, suit ):
  if rank == 1: return AceCard( rank, suit )
  elif 2 <= rank < 11: return NumberCard( rank, suit )
  elif 11 <= rank < 14: return FaceCard( rank, suit )
  else:
    raise Exception( "Rank out of range" )

仅仅是简化工厂函数不应该是我们重构焦点的全部。我们还应该看到这次的重构导致__init()__方法变得复杂了,做这样的权衡是正常的。


427ae76760c51a7d2c3df4d834a823687fe00a2a
相关文章
|
11天前
|
Python
python魔法方法如何应用
【4月更文挑战第12天】这个Python示例展示了类继承和方法重写。`Student`类继承自`Person`,并覆盖了`say_hello`方法。通过`super().__init__(name)`调用父类的`__init__`初始化`name`属性,`Student`添加了`age`属性,并在重写的`say_hello`中使用。创建`Student`实例`student`并调用其`say_hello`,输出定制的问候信息。
19 1
|
4天前
|
存储 关系型数据库 MySQL
Python搭建代理IP池实现存储IP的方法
Python搭建代理IP池实现存储IP的方法
|
4天前
|
Python
Python动态IP代理防止被封的方法
Python动态IP代理防止被封的方法
|
5天前
|
数据采集 存储 安全
python检测代理ip是否可用的方法
python检测代理ip是否可用的方法
|
6天前
|
数据可视化 测试技术 Python
在Python和R中使用交叉验证方法提高模型性能
在Python和R中使用交叉验证方法提高模型性能
|
6天前
|
存储 监控 开发工具
对象存储OSS产品常见问题之python sdk中的append_object方法支持追加上传xls文件如何解决
对象存储OSS是基于互联网的数据存储服务模式,让用户可以安全、可靠地存储大量非结构化数据,如图片、音频、视频、文档等任意类型文件,并通过简单的基于HTTP/HTTPS协议的RESTful API接口进行访问和管理。本帖梳理了用户在实际使用中可能遇到的各种常见问题,涵盖了基础操作、性能优化、安全设置、费用管理、数据备份与恢复、跨区域同步、API接口调用等多个方面。
37 9
|
7天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
44 0
|
12天前
|
机器学习/深度学习 人工智能 算法
|
12天前
|
安全 Python
python字典的内置方法
Python字典主要方法包括:`keys()`(返回所有键)、`values()`(返回所有值)、`items()`(返回所有键值对)、`get()`(安全取值,键不存在时返回默认值)、`setdefault()`(设置默认值)、`update()`(合并字典)、`pop()`(删除并返回值)、`clear()`(清空字典)、`copy()`(浅拷贝)、`fromkeys()`(新建字典并设置默认值)、`popitem()`(随机删除键值对)。
8 0
|
13天前
|
索引 Python
python元组内置方法知识
Python元组方法简介:`count()`统计元素出现次数,如`t.count(2)`返回3;`index()`获取元素首次出现的索引,如`t.index(3)`返回2;`insert(index, element)`在指定位置插入元素,如`t.insert(1, &#39;a&#39;)`;`remove(element)`删除元素,如`t.remove(2)`返回 `(1, 3)`;`pop()`删除并返回最后一个元素,如`t.pop()`返回3;`reverse()`反转元组元素,如`t.reverse()`后`t`变为`(3, 2, 1)`。
17 5