Python面向对象—初级
一、概述
面向过程:根据业务逻辑从上到下写代码,也是初学者最容易接受的编程方式。函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可(python支持函数式编程)。面向对象:对函数进行分类和封装,让开发变得更加便捷和高效。(python也支持面向对象编程)下面我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)
二、创建类和对象
面向对象编程是一种编程方式,此编程方式的实现需要使用 “类” 和 “对象” 来实现,因此面向对象编程其实就是对 “类” 和 “对象” 的使用。类相当于一个模板,模板里可以包含多个函数,函数里实现一些功能;对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。
class Bar:
#创建类中的函数
def foo(self,arg):
#函数体
#根据类Bar创建对象obj
obj = Bar()
class是关键字,表示类;创建对象,类名称后加括号即可,类中定义的函数叫做 “方法”,类中的函数第一个参数必须是self。
下面我们再来看一个例子:
# 创建类
class Foo:
def Bar(self):
print 'Bar'
def Hello(self, name):
print 'i am %s' %name
# 根据类Foo创建对象obj
obj = Foo()
obj.Bar() #执行Bar方法
obj.Hello('Tom') #执行Hello方法
在学习面向对象的三大特性之前我们需要知道构造方法的特殊作用,即在obj = 类名()时:—>创建对象—>通过对象自动执行类中的构造方法。
三、面向对象三大特性
面向对象的三大特性是指:封装、继承和多态。而在Python是原生多态的,所以我们就主要讨论封装和继承。
封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
第一步:将内容封装到某处
'''************************封装****************************'''
#创建类
class Person:
def __init__(self,name,age):#--->称为构造方法,根据类创建对象时自动执行
self.name = name
self.age = age
def show(self):
print('%s--%s' % (self.name,self.age))
#根据类Person创建对象--->然后自动执行Person类的__init__方法
hs = Person('hongsong',24)#--->将hongsong和24分别封装到对象hs的self.name和self.age属性中
hs.show()#---->调用类中的show()方法打印信息
输出:
hongsong--24
self 是一个形式参数,当执行 hs = Person(‘hongsong’,24)时,self 其实就等于 hs。所以,内容其实被封装到了对象 hs 中,对象中有 name 和 age 属性。
第二步:从某处调用被封装的内容
调用被封装的内容时,有两种情况:通过对象直接调用;通过self间接调用。
1、通过对象直接调用被封装的内容
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
obj = Person('hongsong',24)
print(obj.name)#直接调用obj对象的name属性
print(obj.age)#直接调用obj对象的age属性
2、通过self间接调用被封装的内容
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def show(self):
print('%s--%s' % (self.name,self.age))
obj = Person('hongsong',24)
obj.show()# Python默认会将obj传给self参数,即:obj.show(obj),所以,此时方法内部的 self = obj,即:self.name 是 hongsong ;self.age 是 24
总结:对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。
继承
继承,即:子可以继承父的内容。在我们接触继承这个概念的时候,也会遇到父类和子类,基类和派生类的概念。
伪代码:
class 父类:
def 父类中的方法(self):
do something
class 子类(父类):-->子类继承父类,即拥有了父类中的所有方法
pass
son = 子类()-->创建子类对象
son.父类中的方法()-->执行从父类中继承的方法
下面我们来看看具体的例子:
class F:#父类
def f1(self):
print('F.f1')
def f2(self):
print('F.f2')
class S(F):#子类
def s1(self):
print('S.s1')
obj = S()#创建子类对象
obj.s1()#执行子类中的方法
obj.f2()#执行父类中的方法
输出:
S.s1
F.f2
若要防止执行父类中的方法,可以在子类中重写父类中的方法,如下代码所示:
class F:#父类
def f1(self):
print('F.f1')
def f2(self):
print('F.f2')
class S(F):#子类
def s1(self):
print('S.s1')
def f2(self):#----重写父类中的f2,防止执行父类中的f2方法-----#
print('S.f2')
obj = S()#创建子类对象
obj.s1()#执行子类中的方法
obj.f2()
输出:
S.s1
S.f2
在子类中如果要求有选择性的执行父类中的方法,可以这样写:
class F:#父类
def f1(self):
print('F.f1')
def f2(self):
print('F.f2')
class S(F):#子类
def s1(self):
print('S.s1')
def show(self):
print('S.show')
super(S, self).f1() # 执行父类(基类)中的f1方法
F.f2(self)#执行父类(基类)中的f2方法 #通过类名调用f2需要把self传给f2
obj = S()#创建子类对象
obj.s1()#执行子类中的方法
obj.show()
输出:
S.s1
S.show
F.f1
F.f2
多重继承(待续…)
多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,Java是原生多态。
注意
类和对象在内存中是如何保存?
类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图:
如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该指针指向当前对象的类。
当通过 obj1 执行 【方法一】 时,过程如下:
根据当前对象中的类对象指针找到类中的方法,将对象 obj1 当作参数传给方法的第一个参数 self 。