面向对象编程 -- 封装、继承

面向对象编程三要素:封装、继承和多态。本文主要看和封装、继承相关的概念;在python中多态的概念比较模糊,本文不做讨论。

1 封装

封装:将数据和操作组装到一起,对外只暴露一些接口供类外部或子类访问,隐藏数据和操作的实现细节。

在其他面向对象语言,比如java中,属性访问控制一般有三种状态:private、protectd、public。python中没有什么东西是完全不可见的,没有任何机制可以强制性的隐藏数据。所以在python中不存在真正的只能在对象内部访问的属性。
一个被大多数的python程序员遵守的约定:以下划线开头的变量应该被当作非公有属性对待,即它应该被当作是实现细节,其修改应该是不被察觉的。

1.1 名称管理

python中有一种机制对类成员的私有化提供有限的支持,称为名称管理
任何以至少两个下划线开头、至多一个下划线结尾的标识符,如__spam,都会被转换为_classname__spam的形式,其中classname是当前的类名。这种名称管理机制不考虑标识符实际归属哪个命名空间,只要它发生在类的定义中,就会自动生效。

class Chinese:
"""A sample example class"""
nationality = 'China' def __init__(self, name, age, gender):
self.name = name
self.__age = age
self.gender = gender def __str__(self):
return '{}(name={}, age={}, gender={})'.format(self.__class__, self.name, self.__age, self.gender) xm = Chinese('xiaoming', 18, 'male')
print(xm.__dict__) # {'gender': 'male', 'name': 'xiaoming', '_Chinese__age': 18}
print(xm) # <class '__main__.Chinese'>(name=xiaoming, age=18, gender=male)
print(xm.__age) # AttributeError: 'Chinese' object has no attribute '__age'
  • __age在类中被自动转化为_Chinese__age保存在实例的命名空间中;
  • 类内部出现的__age形式的标识符都会被自动转换,所以__str__方法可以访问本例中的__age属性;
  • 在类外部(包括在子类中),无法访问__age属性,因为实例命名空间中并不存在该属性。

继承

继承:对现有类的一种复用机制。如果相对现有的类做一些个性化的修改,可以通过继承实现,而不是直接修改原类。

python的继承语法如下:

class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>

BaseClassName代表被继承的类,称为基类或者父类。
DerivedClassName称为子类。除了添加了父类,子类的定义和实例化和普通的类并没有什么区别。可以通过BaseClassName.__bases__查看其父类。

  1. 子类可以引用父类命名空间中的所有属性。属性的查找顺序:实例-->子类-->父类-->父类的父类...-->object。python3中所有的类都隐性继承自object类。
  2. 子类可以重写父类的属性。一旦属性重写,对于子类或子类之前开始的属性查找,父类对应的属性相当于被屏蔽掉了。
  3. 如果子类要重写初始化方法,最好通过扩展父类的初始化方法实现,即调用父类的初始化方法,并实现自己的个性化扩展。
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age def reply(self):
return self.speak() def speak(self):
return 'Hello world' class Cat(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age)
self.breed = breed def speak(self):
return 'Cat Miaow' print(Cat.__bases__) # (<class '__main__.Animal'>,)
garfield = Cat('Garfield', 10, 'Garfield')
print(garfield.reply()) # Cat Miaow

super().__init__引用Animal之前的祖先类的初始化方法。

多继承

python是支持多继承的,其语法如下:

class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>

多继承要解决的主要问题是属性搜索顺序:
1. 将类及其祖先类按照搜索优先级从高到低排列生成一个列表的过程称为类的线性化。
2. MRO: Method Resolution Order, 指用于类线性化的规则,python3用的是C3算法。C3算法可以保证线性化的单调性,单调性是指:如果在类C的线性化中,C1的优先级高于C2,那么C的所有子类的线性化中,C1的优先级高于C2。
3. 可以通过 DerivedClassName.__mro__ 查看类的线性化结果。

想了解C3算法的具体实现,可以参考文章:https://www.python.org/download/releases/2.3/mro/

其他

数据属性和方法属性可能会出现标识符冲突,这会导致非预期的属性重写(对于标识符而言,赋值即定义),这在大型项目中会引起难以定位的bugs。为了避免标识符冲突,使用一些约定最小化冲突概率是明智的。参考方案:

  • 大写方法属性的首字母,给数据属性标识符添加特定的前缀
  • 使用动词标识方法属性,使用名词标识数据属性

参考:

1 file:///Library/Frameworks/Python.framework/Versions/3.5/Resources/English.lproj/Documentation/tutorial/classes.html

 
 
 

python面向对象编程 -- 封装、继承的更多相关文章

  1. python 面向对象及封装继承和多态

    ######装饰器######装饰器的概念 - 装饰器的实现是函数里面嵌套函数;- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;- 装饰器需要传递一个函数, ...

  2. Python - 面向对象编程 - 多继承

    继承的详解 https://www.cnblogs.com/poloyy/p/15216652.html 这篇文章讲的都是单继承,Python 中还有多继承 Python 多继承的背景 大部分面向对象 ...

  3. Python 面向对象编程 继承 和多态

    Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...

  4. Python面向对象编程——继承与派生

    Python面向对象编程--继承与派生 一.初始继承 1.什么是继承 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题. 继承是一种创 ...

  5. Python面向对象中的继承、多态和封装

    Python面向对象中的继承.多态和封装 一.面向对象的三大特性 封装:把很多数据封装到⼀个对象中,把固定功能的代码封装到⼀个代码块, 函数,对象, 打包成模块. 这都属于封装思想. 继承:⼦类可以⾃ ...

  6. python面向对象编程进阶

    python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...

  7. Python面向对象编程(下)

    本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...

  8. python面向对象编程学习

    python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

  9. Python面向对象04 /封装、多态、鸭子类型、类的约束、super

    Python面向对象04 /封装.多态.鸭子类型.类的约束.super 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 3. 鸭子类型 4. 类的 ...

随机推荐

  1. Flutter之 LimitedBox、Offstage、OverflowBox、SizedBox详解

    1. LimitedBox A box that limits its size only when it's unconstrained. 1.1 简介 LimitedBox,通过字面意思,也可以猜 ...

  2. mysql的主从复制

    一.主从复制简介 二.主从复制原理 四.主从复制基本故障处理 五.延时从库 六.半同步复制 七.过滤复制 四.主从复制基本故障处理 SQL 线程为NO 一般情况下,因为主库一开始本来就有一些存在的库, ...

  3. debug2

    调试常用功能介绍 日常java开发中实际写代码的时间并不会很多,花在整理思路,代码重构,调试bug会占用很大部分时间. 熟练掌握调试工具,了解调试相关技巧,是java开发中减少调试时间,提高效率不可或 ...

  4. jquery选择基础

    1 元素选择器 之前不熟悉的是如: $("input.cls1"); 这种用法 2 属性选择器 包含name属性的input元素, 如 $("input[name]&qu ...

  5. Django的一些操作与视图函数

    一 . Django的安装 pip install django==1.14.6 # 后面的数字是django的版本 二 .  通过命令行(cmd)来创建Django项目 1. 切换到保存项目的文件夹 ...

  6. LoadRunner Vuser接口测试脚本 Post举例

    发送内容为JSON的POST请求需要加入"EncType=application/json",表单参数不需要.(JAVA API) // POST接口调用 web.custom_r ...

  7. 一、zipkin

    zipkin是Twitter基于google的分布式监控系统Dapper(论文)的开发源实现,zipkin用于跟踪分布式服务之间的应用数据链路(具体就是收集微服务之间的调用情况,然后处理调用之间数据延 ...

  8. iis7.0 发生未知 FastCGI错误,错误代码 0x8007010b 的解决办法

    错误提示 修改该网站所对应的应用程序池 进程模型->标识 修改为:LocalSystem

  9. 使用 Travis CI 自动部署 Hexo 站点至 GitHub Pages

    Hexo 与 GitHub Pages 安装配置请参考:Hexo 与 GitHub Pages 本文源码与生成的静态文件在同一项目下,源码在 source 分支,静态文件在 master 分支 新增 ...

  10. Matlab提供了两种除法运算:左除(\)和右除(/)

    Matlab提供了两种除法运算:左除(\)和右除(/).一般情况下,x=a\b是方程a*x =b的解,而x=b/a是方程x*a=b的解.例:a=[1  2  3; 4  2  6; 7  4  9]b ...