python 面向对象
三天不练门外汉,最重要的是坚持!
武sir的博客讲的很清楚,关键是课非常好,一遍就听懂了,奉上原文地址:http://www.cnblogs.com/wupeiqi/p/4493506.html
面向过程:根据业务逻辑从上到下依次垒代码
函数式编程:根据不同的功能需求编辑不同的函数,使用时调用函数即可,一个函数有不同的方法。
面向对象:将实现一类功能的函数封装到一起,每个类可以创建多个对象.面向对象编程也叫OOP。
面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 实例变量:定义在方法中的变量,只作用于当前实例的类。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是 模拟"是一个(is-a)"关系(例,Dog是一个Animal)。也可称为“父类”与“子类”
- 实例化:创建一个类的实例,类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
一,类和对象
面向对象编程是一种编程方式,在面向过程中,最重要的两个概念就是类和对象。面向对象编程就是对“类”和“对象”的使用。
类是什么:类可以看做我们做一件事的“模板”,模板里可以包含多个函数,函数实现具体的功能。
从程序设计的角度来看,类是python的程序组单元,就像函数和模块一样,类具有三个重要的独到之处,使其在建立新对象是更有用。
1.多重实例
类可以看做是对象的生产车间,每次调用类,都产生一个独立的命名空间的新对象。每个由类产生的对象都能读取类的属性,并获取自己的命名空间来存储数据,这些数据对每个对象来说都是不同的。
2.通过继承实现定制
我们可以在类的外部重新定义其属性,从而扩充这个类。
3.运算符重载
通过提供特定的协议方法,类可以定义对象来相应在内置类型上的运算。
对象是什么:对象就是根据模板创建的实例,将类实例化后我们便可以使用实例对象来执行类的函数来完成具体的任务。
创建对象:类名后面加括号即可
· 通过对象执行方法:对象名.方法名()
#!/use/bin/env python #_*_ coding:utf_8 _*_ #定义类 class FU: #注意没有括号 #创建类中的函数,类中的函数称为方法 def welcome(self): print('创建第一个类') def hello(self,name):# self为形式参数,必填。 print('hello,%s'%name) #定义对象 obj = FU() obj.welcome() #执行welcome方法 obj.hello('zhang sir') #执行hello()方法
二,面向对象的三大特性
面向对象编程:创建对象,通过对象执行方法
函数式编程:执行函数
面向对象有三大特性:封装,继承,多态(面试必考有木有)
(1)封装
封装分为两步:封装和调用
step1 封装
将实现一类功能的方法封装到一起。
class F1: def __init__(self,name,age): #构造方法,根据类创建的对象自动执行 self.Name = name self.Age = age #根据类创建对象obj #自动执行__init__方法 obj1 = F1('zhang','20') #将zhang,20封装到obj1 obj2 = F1('wang','30') #将wang,30封装到obj1
self是一个形式参数,当执行obj1 = F1('zhang','20') 时,self等于obj1,当执行obj2 = F1('wang','30') 时,self等于obj2.所以内容封装到了对象中,每个对象都有name和age属性。
step2 调用
调用被封装的内容时,有两种方式:
1.通过对象直接调用被封装的内容。对象.属性名
class F1: def __init__(self,name,age): #构造方法,根据类创建的对象自动执行 self.Name = name self.Age = age #根据类创建对象obj #自动执行__init__方法 obj1 = F1('zhang','20') #将zhang,20封装到obj1 obj2 = F1('wang','30') #将wang,30封装到obj1
2.通过self间接调用被封装的内容
class F1: def __init__(self,name,age): #构造方法,根据类创建的对象自动执行 self.Name = name self.Age = age def info(self): print(self.Name) print(self.Age) #根据类创建对象obj #自动执行__init__方法 obj1 = F1('zhang','20') #将zhang,20封装到obj1 obj1.info() #python 默认将obj1传递给self,即obj1.info(obj1),self.Name = 'zhang';self.Age = '20' obj2 = F1('wang','30') #将wang,30封装到obj1 obj2.info()
掉节操的例子
class foo: def __init__(self,name,age): self.name = name self.age = age def option1(self): print('%s,%s,上山去砍柴'%(self.name,self.age)) def option2(self): print('%s,%s,开车去东北'%(self.name,self.age)) def option3(self): print('%s,%s,XXOO'%(self.name,self.age)) obj2 = foo('小明','10') obj2.option1() obj2.option3() obj1 = foo('老王','40') obj1.option2() >>> 小明,10,上山去砍柴 小明,10,XXOO 老王,40,开车去东北
(2)继承
对于python语法而言,类和对象可以简化为表达式:object.attribute,当遇到类时,便会进行如下操作:、
找到attribute首次出现的地方,先搜索object,然后在搜索改对象之上的所有类,由下至上,由左至右。子类会继承父类的属性,当子类重新定义父类的变量名时,便会覆盖父类定义的属性。
对于面向对象的继承来说,其实就是讲多个类共有的方法提取到父类中,子类仅需继承父类而不必要一一实现每个方法。
class C1: def func(): pass class C2(C1) #子类继承父类,拥有所有的父类的方法 def obj() pass zi = C2() #创建子类对象 zi.func() #执行从父类中继承的方法
多继承
上面的例子我们仅继承了一个父类的方法,但对于python来说,它的类可以继承多个类,而Java和C#只能继承一个类。
例如:class C3(c2,c1):C3类优先继承c2,然后继承c1,按照从左至右的方式依次继承,多继承中,共同的父类处于最低优先级。
那么问题来了,当python继承多个类,类里面还有相同的方法时,哪一个才会被使用呢?
对于解决这个问题,python采用两种方式,分别是深度优先和广度优先
当类是经典类时,多继承的情况下,采用深度优先
当类是新式类时,多机场的情况下,采用广度优先
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。object是一个基类,或称之为元类。在python2.x上,不继承object类的称之为经典类,继承了object类的称之为新式类关于它们的区别,可以阅读以下python2手册中的这个部分:https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
在python官网中提到:
所以,我们使用2.7以后的版本时,默认继承object类。其实广度优先的意思就是我们上文提到的在多继承中,共同的父类处于最低优先级。
三、多态
多态值传递的参数可以有多种形态,多种类型,Python默认支持,比如万能参数*args,**kwargs
对于Java、C#来说,是不支持多态的,必须制定参数的类型,下面是用python写的Java伪代码>_<
def func(int arg) print(arg) func(123) func('alex') #执行的时候会报错
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' # 由于在Java或C#中定义函数参数时,必须指定参数的类型 # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类 # 而实际传入的参数是:S1对象和S2对象 def Func(F1 obj): """Func函数需要接收一个F1类型或者F1子类的类型""" print obj.show() s1_obj = S1() Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' def Func(obj): print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj)