目录
1.面向对象的理解
在学习编程的过程中经历以下阶段:
面向过程——函数式编程——面向对象编程
随着观念的转变,编程的思想越来越抽象化,唯一的思路就是使得代码的重用性升高,代码的理解层面升级,Python是面向对象编程的一大优势语言,在其语法的实现过程中增加了很多灵活的设定,比传统的C++开发效率更高,但是并没有C和Python的运行效率和利用硬件的效率高。
2.建立类
由上图所示,需要关键字class,和自己定义的类名进行类的创建,self关键参数是必不可少的,因为它代表对象。
self的两个作用:
- 传对象参数给类内方法使用,一般通过__init__()方法将对象参数传入
- 一般将公共参数用self关键字封装给对象
这就引入面向对象的三大特性:
3. 面向对象的三大特性
面向对象三大特性:封装、继承、多态
3.1 特性一:封装
上文已经提到对于类中关键字self的理解:建立对象的时候,self就代表对象本身,但是在类中要统一表示,即为封装。
封装就是将公共用的参数(字段)和函数(方法)在类中进行统一的表示,对于任何用该类建立的对象都可进行对象+’.'进行该字段和方法的访问。
封装是面向对象最基本的思想,一个好的封装思想会让开发效率事半功倍。
封装面临两个步骤
- 将内容封装到某处
- 从某处调用封装的内容
第一步:将内容封装到某处
self 是一个形式参数,
当执行 obj1 = Foo(‘wupeiqi’, 18 ) 时,self 等于 obj1
当执行 obj2 = Foo(‘alex’, 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存
第二步:从某处调用封装内容
调用被封装的内容时,有两种情况:
- 通过对象直接调用 (类外)
- 通过self间接调用 (类内)
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。
构造方法:__init__(self)
init构造方法是类创建对象的时候调用的第一个方法:
类+():调用构造方法的格式就是类名加括号,而构造方法内部一般放入初始化字段和其他方法初始化对象使用;
构造方法与其他方法类似,也可进行参数的传入
self.inner_name = outer_name
类似于上述描述,以区分传入的参数来源于外部,与内部的self.参数进行封装的类字段不同。
如果有多个相同的方法和参数,编程一般转为面向对象的编程
3.2 特性二:继承
3.2.1 基本格式
# 继承的基本格式:
class father: # 父类 基类
pass
class son(father): # 子类 派生类
pass
上述格式即完成了子类继承父类的基本功能。
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
3.2.2 继承的特点
- 子类可以适用父类中所有的字段和方法(除了私有字段和方法)
- 子类可以重写父类的字段和方法(只要在子类中使用重名的方法/字段变量名即可)
- 子类重写父类方法之后若想执行父类方法,可采用以下方式同样适用于init构造方法,而且一般重写内部模块中的构造方法都需要先调用父类的构造方法:
'''方法一'''
def foo(self):
supper(son, self).foo()
pass
'''方法二'''
def foo(self):
father.foo(self)
pass
3.2.3 多继承
面临两个问题:
- 是否可以继承多个类(是,java和c#不允许)
- 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?(采用深度优先、广度优先的准则)
先明白经典类和新式类:如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类(此处目前还未用到,并未很理解)
1. 经典类——深度优先
- 深度优先的类,需要在一条线上寻找到底(一直到共同的基类)
- 如果基类之外的父类未找到,从头依次向左按照深度优先准则继续寻找
class E(object):
def bar1(self):
print ('E.bar')
class D(E):
def bar1(self):
print ('D.bar')
class C(E):
def bar1(self):
print ('C.bar')
class B(D):
def bar1(self):
print ('B.bar')
class A(B, C):
def bar(self):
print ('A.bar')
a = A()
a.bar1()
'''# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果C类中么有,则继续去E类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C-->E
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
'''
2. 新式类——广度优先没起作用实验失败(以后补充)
此处只拿来一个例子见识objec新式类的写法,以后再进行补充
class E(object):
def bar(self):
print 'E.bar'
class D:
def bar(self):
print 'D.bar'
class C(E):
def bar(self):
print 'C.bar'
class B(D):
def bar(self):
print 'B.bar'
class A(B, C):
def bar(self):
print 'A.bar'
a = A()
a.bar()
'''# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
'''
3.3 特性三:多态
多态即为形参可以代表任何形式的变量,在Python中内部机制即支持多态,此处仅进行了解即可。
4 总结:
- 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
- 类 是一个模板,模板中包装了多个“函数”供使用
- 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
- 面向对象三大特性:封装、继承和多态
5 类和对象在内存中是如何保存
如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值指向当前对象的类。
当通过 obj1 执行 【方法一】 时,过程如下:
- 根据当前对象中的 类对象指针 找到类中的方法
- 将对象 obj1 当作参数传给 方法的第一个参数 self