# 面向对象概述

# 面向对象

传统的命令式语言有无数重复性代码,虽然函数的诞生减缓了许多重复性,但随着计算机的发展,只有函数依然不够,需要把更加抽象的概念引入计算机才能缓解(而不是解决)这个问题,于是 OOP 应运而生。

  • 类:一群有着相似性的事物的集合,这里对应 Python 的 class。

    • python中所有数据类型都是对象,一个对象可以被多个变量所指向。
    • python中的一些数据类型,例如int,string是不可变的,在修改其值时实际上是创建了一个新的对象并让变量指向其。
    • 对于不可变对象(字符串、整型、元组等等),所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+= 等等)更新不可变对象的值时,会返回一个新的对象。
    • python中变量可以删除,但对象无法删除,只会被垃圾回收系统处理
  • 对象:集合中的一个事物,这里对应由 class 生成的某一个 object

  • 属性:对象的某个静态特征

    • 私有属性是以__(双下划线)开头的属性,举例:self.__属性名,只能在类内部调用,类外部无法访问。
    • 和函数并列地声明并赋值便可以设置类的常量
  • 函数:对象的某个动态能力

    • 静态函数

      • 静态函数和类没有什么关联,第一个参数也没有什么特殊性;一般用来做一些简单独立的任务,既方便测试也能优化代码结构
      • 需要在函数前一行加上@staticmethod 来表示
    • 类函数

      • 类函数的第一个参数一般为cls,表示传递一个类进来
      • 最常用的功能是实现不同的init构造
      • 类函数需要装饰器 @classmethod 来声明
    • 成员函数

      • 最正常的类的函数
      • 不需要任何编译器什么
      • 第一个参数self表示当前对象的引用

class Document():
  
    WELCOME_STR = 'Welcome! The context for this book is {}.'
  
    def __init__(self, title, author, context):
        print('init function called')
        self.title = title
        self.author = author
        self.__context = context
  
    # 类函数
    @classmethod
    def create_empty_book(cls, title, author):
        return cls(title=title, author=author, context='nothing')
  
    # 成员函数
    def get_context_length(self):
        return len(self.__context)
  
    # 静态函数
    @staticmethod
    def get_welcome(context):
        return Document.WELCOME_STR.format(context)


empty_book = Document.create_empty_book('What Every Man Thinks About Apart from Sex', 'Professor Sheridan Simove')


print(empty_book.get_context_length())
print(empty_book.get_welcome('indeed nothing'))

########## 输出 ##########

init function called
7
Welcome! The context for this book is indeed nothing.

# 鸭子类型

鸭子类型是动态类型语言判断一个对象是不是某种类型时使用的方法,也叫做鸭子判定法。简单的说,鸭子类型是指判断一只鸟是不是鸭子,我们只关心它游泳像不像鸭子、叫起来像不像鸭子、走路像不像鸭子就足够了。换言之,如果对象的行为跟我们的预期是一致的(能够接受某些消息),我们就认定它是某种类型的对象。

在Python语言中,有很多bytes-like对象(如:bytes​、bytearray​、array.array​、memoryview​)、file-like对象(如:StringIO​、BytesIO​、GzipFile​、socket​)、path-like对象(如:str​、bytes​),其中file-like对象都能支持read​和write​操作,可以像文件一样读写,这就是所谓的对象有鸭子的行为就可以判定为鸭子的判定方法。再比如Python中列表的extend​方法,它需要的参数并不一定要是列表,只要是可迭代对象就没有问题。

说明:动态语言的鸭子类型使得设计模式的应用被大大简化。