先来简单解释几个概念。
类:一群有着相似性的事物的集合,这里对应 Python 的 class。
对象:集合中的一个事物,这里对应由 class 生成的某一个 object,比如代码中的 harry_potter_book。
属性:对象的某个静态特征,比如上述代码中的 title、author 和 __context。
函数:对象的某个动态能力,比如上述代码中的 intercept_context () 函数。
在工程实践中,随着复杂度继续提升,你可能会想到一些问题:
如何在一个类中定义一些常量,每个对象都可以方便访问这些常量而不用重新构造?
如果一个函数不涉及到访问修改这个类的属性,而放到类外面有点不恰当,怎么做才能更优雅呢?
既然类是一群相似的对象的集合,那么可不可以是一群相似的类的集合呢?
第一个问题,在 Python 的类里,你只需要和函数并列地声明并赋值,就可以实现这一点,例如这段代码中的 WELCOME_STR。一种很常规的做法,是用全大写来表示常量,因此我们可以在类中使用 self.WELCOME_STR ,或者在类外使用 Entity.WELCOME_STR ,来表达这个字符串。
而针对第二个问题,我们提出了类函数、成员函数和静态函数三个概念。它们其实很好理解,前两者产生的影响是动态的,能够访问或者修改对象的属性;而静态函数则与类没有什么关联,最明显的特征便是,静态函数的第一个参数没有任何特殊性。
具体来看这几种函数。一般而言,静态函数可以用来做一些简单独立的任务,既方便测试,也能优化代码结构。静态函数还可以通过在函数前一行加上 @staticmethod 来表示,代码中也有相应的示例。这其实使用了装饰器的概念,我们会在后面的章节中详细讲解。
而类函数的第一个参数一般为 cls,表示必须传一个类进来。类函数最常用的功能是实现不同的 init 构造函数,比如上文代码中,我们使用 create_empty_book 类函数,来创造新的书籍对象,其 context 一定为 'nothing'。这样的代码,就比你直接构造要清晰一些。类似的,类函数需要装饰器 @classmethod 来声明。
成员函数则是我们最正常的类的函数,它不需要任何装饰器声明,第一个参数 self 代表当前对象的引用,可以通过此函数,来实现想要的查询 / 修改类的属性等功能。