Python封装机制及实现方法

不光是Python, 大多数面向对象编程语言(如C++, Java等)都具备三个典型特征, 即封装, 继承多态.

  • 多态

术语多态(Polymorphism), 字面意思是一个事物有多种形态.

在面向对象程序设计中, 可以这么理解多态: 不同的对象拥有相同的方法, 对不同的对象调用同一个方法, 不同的对象有不同的响应.

对同一个方法, 不同的对象都有响应; 这大致意味着即便不知道变量绑定的是哪个对象, 也能够对其执行操作, 且操作的行为将随对象所属的类型而异.

  • 封装

封装(Encapsulaiton) 指的是向外隐藏不必要的细节. 这听起来有点像多态, 这两个概念很像, 因为它们都是抽象的原则, 但封装不同于多态.

  • 多态让你无需知道对象所属的类(对象的类型)就能调用其方法;
  • 封装让你无需知道对象的构造(内部实现细节)就能使用它.

面向对象是以数据为核心的, 将数据和对数据的操作, 封装在类中.

  • 继承

继承, 是根据已有的类创建新的类, 实现代码重用.

Python类的封装

简单的理解封装, 就是在设计类时, 将一些属性和方法隐藏在类的内部, 这样在使用此类时, 将无法直接以类名.属性类名.方法的形式调用这些属性或方法, 而只能用未隐藏的类方法间接操作这些隐藏的属性和方法.

那么, 类为什么要进行封装, 这样做有什么好处呢?

  • 封装机制保证了类内部数据结构的完整性, 因为使用类的用户无法直接看到类中的数据结构, 只能使用类允许的公开的数据, 很好地避免了外部对内部数据的影响, 提高了程序的可维护性;
  • 对一个类实现良好的封装, 用户只能借助暴露出来的类方法来访问数据, 我们只需要在这些暴露的方法中加入适当的控制逻辑, 即可轻松避免用户对类中属性或方法的不合理操作;
  • 对类进行良好的封装, 还可以提高代码的复用性.

在其它面向对象的编程语言(如C++,Java等)中, 类中的属性和方法, 不是公有的就是私有的, 这两种属性的区别如下:

  • public: 公有的属性和方法, 在类的外部, 类内部以及子类中都可以正常访问;
  • private: 私有的属性和方法, 只能在类的内部使用, 类的外部以及子类中都无法使用.

但是, Python中并没有提供public, private这些修饰符, 为了实现类的封装, Python采取了如下方法:

  • 默认情况下, Python类中的属性和方法都是公有的, 它们的名称前都没有下划线_;
  • 如果类中的属性和方法, 其名称以双下划线__开头, 则该属性或方法是私有的.

在Python中, 在类中让名称以两个下划线开头, 并不是真的让其成为了私有的. 其幕后的处理方法是: 在类的定义中, 对所有以两个下划线开头的名称都进行转换, 即在开头加上一个下划线和类名. 这样, 就不能通过原来的名称来访问了, 从而实现私有的效果. 但只要知道这种幕后处理手法, 就能从类外访问私有的属性或方法, 然而不应该这样做. 总之, 你无法禁止别人访问对象的私有方法和属性, 但这种名称修改方式发出了强烈的信号, 让他们不要这么做.

注解

在C++中, 提供了修饰符public, protectedprivate, 在语法层面声明属性或方法的访问权限;

在Python中, 是通过名称转换的方式, 以一种”投机取巧”的方式, 实现类似的效果.

如果不希望名称被修改, 又想发出不要从外部访问属性或方法的信号, 可以用一个下划线开头, 这虽然只是一种约定, 但也有一些作用. 例如, from module import *就不会导入以一个下划线开头的名称.

注解

不只是类中, 在模块中以一个下划线开头的名称, 也同样发出了一种强烈的信号, 即不希望使用者在外部访问它们.