面向对象编程——Object Oriented Programming,简称OOP
是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象的基本特征
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
如何创建类:
class 类名:
pass
实例:
#使用class创建一个Bar类,类中有个foo方法:
class Bar:
def foo(self,arg):
print(self,arg)
a1 = Bar()
print(a1)
a1.foo(123)
print('=================================================')
z2 = Bar()
print(z2)
z2.foo(666)
查看打印结果:
<__main__.Bar object at 0x000001E2F7054788>
<__main__.Bar object at 0x000001E2F7054788> 123
=================================================
<__main__.Bar object at 0x000001E2F70547C8>
<__main__.Bar object at 0x000001E2F70547C8> 666
构造方法和普通方法:
构造方法,__init__(self,arg)
obj = 类('a1')
普通方法
obj = 类(‘xxx’)
obj.普通方法名()
类中定义的函数叫做方法,带有__init__的函数称为构造方法。
一、封装
将某些内容先封装到一个地方,等到需要的时候直接去调用;
调用的两种方式,通过对象直接调用和通过self间接调用;
直接调用:
class Bar:
def __init__(self,name,age):
self.name = name
self.age = age
def foo(self):
print('name:%s,age:%s'%(self.name,self.age))
#创建z1,z2
z1 = Bar('wang',18)
z2 = Bar('xuan',20)
print(z1,z2)
print(z1.name,z1.age)
print(z2.name,z2.age)
打印结果:
<__main__.Bar object at 0x000002F25E574908> <__main__.Bar object at 0x000002F25E574948>
wang 18
xuan 20
通过self间接调用:
class Bar:
def __init__(self,name,age):
self.name = name
self.age = age
def foo(self):
print('name:%s,age:%s'%(self.name,self.age))
#创建z1,z2
z1 = Bar('wang',18)
z2 = Bar('xuan',20)
#执行类中的方法时,通过self间接调用被封装的内容;
z1.foo()
z2.foo()
打印结果:
name:wang,age:18
name:xuan,age:20
适用场景:
如果多个函数中有一些相同参数时,转换成面向对象;
class DataBaseHelper:
def __init__(self, ip, port, username, pwd):
self.ip = ip
self.port = port
self.username = username
self.pwd = pwd
def add(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接
def delete(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接
def update(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接
s1 = DataBaseHelper('1.1.1.1',3306, 'xuan', '666')
二、继承
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义;
既派生类(子类)可以继承基类(父类)的方法,我们可以将多个类共有的方法提取到父类当中,这样子类仅需继承父类而不必一一实现每个方法;
需要注意圆括号中基类的顺序,若是基类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找基类中是否包含方法;
在类名后面括号中写上另一个类,表示继承了那个类:
class Bar: #创建一个Bar类;
def __init__(self,name,age):
self.name = name
self.age = age
def f1(self):
print('name:%s,age:%s'%(self.name,self.age))
def f2(self):
print('My name is %s'%self.name)
class Son(Bar): #Son继承Bar;
def __init__(self,name):
self.name = name
class Minx(Son): #Minx继承Son
def __init__(self,name):
self.name = name
#创建对象z1
z1 = Son('xuan')
z1.f2()
#创建对象b2
b2 = Minx('wang')
b2.f2()
打印结果:
My name is xuan
My name is wang
多继承
Python同样有限的支持多继承形式;
1、Python的类可以继承多个类,Java和C#中则只能继承一个类;
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先;
在python3.x中都默认为广度优先
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类;
在python2.7中:经典类多继承
class D:
def bar(self):
print 'D.bar'
class C(D):
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()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
经典类多继承
新式类多继承
class D(object):
def bar(self):
print 'D.bar'
class C(D):
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()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
新式类多继承
经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
注意:在上述查找过程中,一旦找到,则寻找过程立即中断;
三、多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。
python鸭子类型:
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)
Python “鸭子类型”
总结:
- 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用;
- 类是创建实例的模板,模板中包装了多个“函数”供使用,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
- 方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
- 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数;
- 和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同;
- 面向对象三大特性:封装、继承和多态;
- 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;
- 动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的;
参考:https://www.cnblogs.com/wupeiqi/p/4493506.html