面向对象

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)

什么是面向对象?

  面向对象就是一种使用'类'和'对象'进行编程的编程方式.

  类是一个模板,模板里可以包含多个函数,类中定义的这些函数称为方法,对象就是根据模板创建的实例,通过实例对象可以执行类中的方法.

类的定义:

    class 类名:    #定义了一个类
      def 函数名(self)    #在类中创建一个方法
        pass
  类的调用:

      x1 = 类名()      #创建一个对象(实例化)一个对象
      x1.函数名()      #通过对象调用一个方法
class Foo:                          #创建一个类
    def func(self):                 #创建一个类中的方法
        print('这是一个类中的方法.')
obj = Foo()                         #根据类创建一个叫做obj的对象
obj.func()                          #通过对象去使用方法
结果:
这是一个类中的方法.

  注意:类中的方法的第一个参数必须是self.

面向对象与函数编程的区别:

  面向对象: 创建对象-->通过对象执行方法

  函数编程: 执行函数

  函数编程的应用场景-->各个函数之间是独立的且无共用数据.

  相较于函数编程,面向对象适用于共用数据的编程场景.

面向对象的三大特性: 封装,继承,多态

  封装(将相关功能封装到一个类中,  将数据封装到一个对象中)

  封装就是将内容封装到某个地方,以后再去调用被封装在某处的内容.在使用面向对象的封装特性时,需要: 

  将内容封装到某处

  从某处调用封装的内容

  将内容封装到某处

class Foo:
    def __init__(self, name, age):    #构造方法,根据类创建对象时自动执行
        self.name = name
        self.age = age
obj = Foo('ZhangSan', 20)             #根据类创建对象并自动执行类的__init__方法

  self是一个形式参数,执行obj = Foo('ZhangSan', 20)是,self等于obj

  此时,name和age被封装到对象obj中,可以理解为obj对象里面有name = 'ZhangSan'和age = 20两个变量.

  从某处调用被封装的内容

  在调用被封装的内容时,有两种情况:

    1.通过对象直接调用

    2.通过self间接调用

  1.通过对象直接调用被封装的内容  

class Foo:
    def __init__(self, name, age):    #构造方法,根据类创建对象时自动执行
        self.name = name
        self.age = age
obj = Foo('ZhangSan', 20)             #根据类创建对象并自动执行类的__init__方法
print(obj.name)
print(obj.age)
结果:
ZhangSan
20

  2.通过self间接调用被封装的内容

class Foo:
    def __init__(self, name, age):    #构造方法,根据类创建对象时自动执行
        self.name = name
        self.age = age
    def detail(self):
        print(self.name)
        print(self.age)
obj = Foo('ZhangSan', 20)             #根据类创建对象并自动执行类的__init__方法
obj.detail()
结果:
ZhangSan
20

   将相关功能封装到一个类中.

class Message:
    def email(self):pass
    def msg(self):pass
    def wechat(self):pass

  将数据封装到一个对象中.

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

obj = Person('张三', 18, '男')
print(obj.name)
print(obj.age)
print(obj.gender)
结果:
张三
18
男

写面向对象的两种小方式

  1.归类+提取公共值

  2.在指定类中编写和当前类相关的所有代码+提取公共值

 1.归类+提取公共值

#归类
class File:
    def file_read(self, file_path):
        pass
    
    def file_update(self, file_path):
        pass
    
    def file_delete(self, file_path):
        pass
    
    def file_add(self, file_path):
        pass
#提取公共值
class File:
    def __init__(self,file_path):
        self.file_path = file_path

    def file_read(self):
        pass

    def file_update(self):
        pass

    def file_delete(self):
        pass

    def file_add(self):
        pass

 2.在指定类中编写和当前类相关的所有代码+提取公共值

class Person:
    def __init__(self, na, gen, age, fig):
        self.name = na
        self.gender = gen
        self.age = age
        self.fight =fig

    def grassland(self):
        self.fight = self.fight - 10

    def practice(self):
        self.fight = self.fight + 90

    def incest(self):
        self.fight = self.fight - 666

  继承

  对面型对象来说,继承就是将多个类共有的方法提取到父类(基类)中,子类(派生类)只需要继承父类而不需要一一实现.

  多继承提高了代码的重用性

class SuperBase:
    def f3(self):    #注意:此处的self仍然是obj
        print('f3')

class Base(SuperBase):  # 父类,基类
    def f2(self):    #注意:此处的self仍然是obj
        print('f2')

class Foo(Base):        # 子类,派生类

    def f1(self):    #此处的self为obj
        print('f1')

obj = Foo()        #创建一个对象
obj.f1()          #使用f1方法
obj.f2()          #自己的类中没有,去Base类中找
obj.f3()          #自己的类中没有,去Base类中找,Base中也没有,去SuperBase类中找
结果:
f1
f2
f3

  继承的原则:先在自己的类中找,没有就去父类中找.(注意:创建的对象不会变,调用这个对象,这个类中的self就一直是这个对象,self不会因为在父类中寻找而变成另外的对象.)

  多继承

class Base1:
    def show(self):
        print('Base1.show')

class Base2:
    def show(self):
        print('Base2.show')

class Foo(Base1,Base2):
    pass

obj = Foo()
obj.show()
结果:
Base1.show

  多继承原则:先在自己的类中找,没有就去父类中找,(上面例子中,先到Base1中找,如果Base1中没有就去Base2中找)先从左边(离自己近的)的父类找.

  1,多继承先找左边

  2,self是哪个类的对象,就从哪个类开始找(自己的类中没有就去父类中找)

  多继承顺序补充:

    python2中类分为经典类和新式类

    python3中只有新式类

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
obj = D()
结果:
python2中:D,B,A,C
python3中:D,B,C,A,object

    上面代码中的类,在python2中都是经典类,经典类继承按照深度优先的顺序继承.

               

     新式类:如果自己或者自己的祖辈继承了object,就是新式类.

class A(object):
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
obj = D()
结果:
python2中:D,B,C,A,object
python3中:D,B,C,A,object


class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
obj = D()
结果:
python3中:D,B,C,A,object

class A(object):
pass
class B(A):
pass
class D(object):
pass
class C(B, D):
pass
class E(object):
pass
class F(E):
pass
class G(D, F):
pass
class H(C, G):
pass
obj = H()
结果:
继承顺序:H,C,B,A,G,D,F,E,object(下图)

    python3中没有经典类,所有的类都是新式类,默认继承object类

    在第二段代码中,class A默认继承了object.新式类的继承顺序按照c3算法.

    

  多态

  多种形态或多种状态(鸭子模型)

  python原生支持多态,没有特殊性

class Foo1:
    def f1(self):  #这里的self传入的参数可以是str,int,dict,list,tuple,set等数据类型
        pass    

def func(arg):    #这里的arg传入的参数可以是str,int,dict,list,tuple,set等数据类型
    arg.f1()

  这种对于传入参数的数据类型的不确定称为多态(在java等语言中,传入的数据类型是确定的)

posted @ 2018-08-27 15:56  Virous1887  阅读(101)  评论(0编辑  收藏  举报