37. 用组合起来的类实现多层结构,不要用嵌套的内置类型

不要在字典,元组等内置类型里嵌套太多次,这样使得代码难以看懂,比较复杂混乱,可以将嵌套的内容抽取出来构造成新的类。

38. 让简单的接口接收函数,而不是类实例

在python中,函数,方法都是一等(first-class)对象,可以像调用对象一样调用他们,因此对于一些简单的接口,可以传入函数而不是非要设计新的类,比如sort(key=len),就是按照长度进行排序,这里对len可以直接怎么使用,当然对于一些复杂的操作,还是需要定义类来使得表达更加清晰。
如果想用函数来维护一个状态,比如在defaultdict中插入新键值对的时候,计算构造了几次键,则可以选择定义新的类,实现call方法,这样也可以直接调用对象达到效果,调用对象的时候会执行call

39. 通过@classmethod多态来构造统一体系中的各种对象

多态机制使同一体系中的多个类可以按照各自独有的方式来实现同一个方法,这意味着这些类都可以满足同一套接口,或者都可以当作某个抽象类来使用,同时,它们又能在这个前提下,实现各自的功能。

1—classmethod设计的目的是什么呢?事实上与Python面向对象编程有关的,由于Python不支持多个的參数重载构造函数,比方在C++里,构造函数能够依据參数个数不一样。能够写多个构造函数。Python为了解决问题,採用classmethod修饰符的方式,这样定义出来的函数就能够在类对象实例化之前调用这些函数,就相当于多个构造函数,解决多个构造函数的代码写在类外面的问题。(其实在内部调用的cls()还是对应于init,但确实间接实现了多态,可以传入不同参数)

2—-类最基本的作用是实例化出一个对象,但是有的时候再实例化之前,就需要先和类做一定的交互,这种交互可能会影响实际实例化的过程,所以必须放在调用构造函数之前。大概也可能是因为这个原因出现了classmethod

3—-一个类中,某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用,可以通过类名进行调用的

4—-@classmethod 定义的类方法是可选构造函数中,我们定义了一个类方法,类方法的第一个参数(cls)指代的就是类本身。类方法会用这个类来创建并返回最终的实例。使用类方法的另一个好处就是在继承的时候,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。

  1. class Data_test2(object):
  2. day=0
  3. month=0
  4. year=0
  5. def __init__(self,year=0,month=0,day=0):
  6. self.day=day
  7. self.month=month
  8. self.year=year
  9. @classmethod
  10. def get_date(cls,data_as_string):
  11. #这里第一个参数是cls, 表示调用当前的类名
  12. year,month,day=map(int,string_date.split('-'))
  13. date1=cls(year,month,day)
  14. #返回的是一个初始化后的类
  15. return date1
  16. def out_date(self):
  17. print "year :"
  18. print self.year
  19. print "month :"
  20. print self.month
  21. print "day :"
  22. print self.day
  23. Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。
  24. 那么如何调用呢?
  25. r=Data_test2.get_date("2016-8-6")
  26. r.out_date()
  27. 输出:
  28. year :
  29. 2016
  30. month :
  31. 8
  32. day :
  33. 1

40. 通过super初始化超类

super可以解决菱形继承问题,按照继承的顺序执行初始化,不要直接用超类名进行初始化。

41. 考虑用mix-in类来表示可组合的功能

尽量少用多重继承,如果既要通过多重继承来方便地封装逻辑,又想避开可能出现的问题,那么就应该把有待继承的类写成mix-in类。这种类只提供一小套方法给子类去沿用,而不定义自己实例级别的属性,也不需要init构造函数。
mix-in形式就是没有init方法和实例属性名,即类里面只有一些方法,子类继承后,可以直接调用这些方法,也可以自己定制(完全修改,或者新的部分+super调用旧的部分)

42. 优先考虑用public属性表示应受保护的数据,而不是private属性表示

python编译器无法绝对禁止外界访问private属性(__name),因为他是通过改名实现的
如果为了防止属性名在继承的时候冲突,则可以用private的形式,其他时候尽量避免使用,方便扩展
想说明该属性受保护,可以写成_name,是可以公开访问的,这是约定俗成的

43. 自定义的容器类型应该从collections.abc继承

像list,dict,tuple这些可以迭代访问的称之为容器类型,如果想实现一些基础类型的扩展,可以在上述这些基础类型上继承,然后实现相关方法。对于一些自己定义的类,想要实现下标访问,需要实现getitem(self, index),想要获取长度使用len函数,就要实现len(self)。
比如我们想实现一个类似list的类,那么我们需要实现哪些方法呢,我们可能不清楚,因此可以继承collections.abc中的基类,如Sequence,Set,Mapping等,它包含了一些必要方法,以及实现了一些方法。如果我们没有实现必要方法,则会报错