面向对象部分详解如下:
一、面向对象
什么是面向对象?
面向对象与面向过程相比:
面向过程:其核心就是过程,过程指的是解决问题的步骤,如先干什么再干什么就好像是一条流水线;该思维方式编程被称为机械式的编程思维。
面向过程的优点:复杂的问题流程化进而流程化
面向过程的缺点:扩展性差(改一个地方其他的地方也必须更改)
面向对象:其核心就是对象,对象指的是特征与功能的结合体,在Python3中世间万物都是对象或在上帝眼里世间万物都是对象即使没有的对象也可以创造出来,这种思维方式被称为上帝式的编程思维。
面向对象的优点:扩展性强
面向对象的缺点:编程的复杂度远高于面向过程
二、类
1、什么是类?
类:指的是一系列具有对象相同特征与功能的结合体
对象:指的是具有特征与功能的结合体
补充:在使用类的时候会产生一个名称空间专门存放具有相同特征与功能结合体,在产生对象的时候会产生一个名称空间专门
用来存放其特有的特征与功能的结合体。
了解:在现实世界中先有对象然后再通过对象总结出类这个概念,但是在程序中必须先定义类然后再通过类来产生对象。
类的举例如下:
class foo: x=11 def __init__(self,name): self.name=name def f(self): print('f') print('11')
调用类产生的对象的例子如下:
obj=foo()
obj.f()
注意:1、在类中任意的Python代码在定义阶段就执行了
2、在__init__中的代码是没有返回值的
三、继承
1、什么是继承?
继承:指的是表示新建的类的方式。新建的类被称为子类或派生类,被继承的类称之为父类或基类或超类。
继承的三大特点:
1、子类可以遗传或重用父类(可以用来解决类与类之间的代码冗余)
2、一个子类可以继承多个父类
3、在继承的背景下Python中类可以分为两种:
新式类:但凡含有object的类与其子子孙孙都是新式类。
注意:在python2中需要自己声明object
经典类:没有object的类其子子孙孙都是经典类。
2、为何要用继承?
是为了解决类与类之间的代码冗余。
3、如何去用继承?
class Foo: def f(self): print('foo_f') class Bar(Foo): def f1(self): print('bar_f1') obj=Bar() obj.f()
4、派生类新方法中重用父类的两个方式
方式一:指名道姓
其特点:1、跟继承无关2、访问的是类中的函数且没有自动传值的效果
例子如下:
class people: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class student(people): def __init__(self,name,age,sex,score): people.__init__(self,name,age,sex) self.score=score def scored(self): print('score') obj=student('liu',18,'male') obj.scored()
方式二:super()在python2中其括号内必须传入(类的 名字,类的对象)
其特点:1、严格依赖继承mro列表 2、访问的是绑定方法并且有自动传值的效果
例子如下:
class people: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class student(people): def __init__(self,name,age,sex,score): super().__init__(name,age,sex) self.score=score def scored(self): print('score') obj=student('liu',18,'male') obj.scored()
5、属性查找顺序
单继承:对象本身-》对象的类-》父类-》父类-》..
多继承:对象本身-》对象的类-》将括号内的按从左到右的顺序查找下去
菱形继承问题的查找方式如下:
新式类:广度优先查找:按照顺序从左到右一个分支一个分支的查找下去,最后一个分支查找顶级类
经典类:深度优先查找:按照顺序从左到右一个分支一个分支的查找下去,第一个分支查找顶级类
补充:在查找新式类时要按照mro列表去查看继承关系如(print(obj.mro()去看对象的mro列表)。
四、组合
1、什么是组合?
组合:指的是某一个类所拥有的属性的值是另一个类的对象
2、为何要用组合?
是为了通过为某一个类添加属性的方式将其关联或组合起来从而达到减少类与类之间的代码冗余。
3、如何去用组合?
例子如下:
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class Student(People): def __init__(self,name,age,sex,score): super().__init__(name,age,sex) self.score=score self.coursed=[] def scored(self): print('score') class Course: def __init__(self,cname,cproice,cprioed): self.cname=cname self.cproice=cproice self.cprioed=cprioed def tell_info(self): print('课程名:%s花费:%s周期:%s'%(self.cname,self.cproice,self.cprioed)) stu=Student('liu',18,'male') python=Course('python',1200,5) stu.coursed.append(python)
五、多态与多态性
1、什么是多态?
多态:指的是同一类或同一事物的不同形态。
2、为何用多态?
在多态性下可以在无需声明类的类型下去使用多态
多态的精髓是:统一
3、如何用多态?
举例如下:
import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def speak(self): print('animal') class People(Animal): def shuo(self): print('people') class Dog(Animal): def sound(self): print('dog') Dog.speak() People.speak()
补充:在多态里使用import abc模块可以强制子类与父类统一,但是也可以在编写的时候就写一样的。
六、封装
1、什么是封装?
封:将名称空间或容器中的名字隐藏起来,这种隐藏对外不对内
装:将名字放入名称空间或容器
2、如何去用?
在属性前加__开头:
封装的三大特点:
1、__开头并不是真正意义上的改变外形且不会真正的限制外部的访问(可以在类中加一个接口用来外部访问)
class Foo: __x=111 # _Foo__x __y=222 # _Foo__y def __init__(self,name,age): self.__name=name self.__age=age def __func(self): #_Foo__func print('func') def get_info(self): print(self.__name,self.__age,self.__x) #print(self._Foo__name,self._Foo__age,self._Foo__x) obj=Foo('egon',18) obj.get_info()
2、__开头只是在类定义阶段改变类中的外形,在类定义阶段后不再改变外形。
3、如果父类不想让子类去覆盖自己的属性可以在属性前加__开头。
class foo: def f1(self): print('foo_f1') self.__f2() def __f2(self): print('foo_f2') class bar(foo): def __f2(self): print('bar_f2') obj=bar() obj.f1()
七、property装饰器
property装饰器可以将函数属性伪装成数据属性
例子如下:
class bmi: def __init__(self,height,weight): self.height=height self.weight=weight @property def bb(self): return self.weight/(self.height**2) obj=bmi(1.72,58) print(obj.bb)
八、绑定与非绑定
绑定方法:(绑定给谁就由谁来调用,谁来调用就将谁当做第一个参数传入)
绑定类的方法:用装饰器@classmethod
@classmeoth
类.boud_method()
(具有自动传参的效果)
绑定对象的方法:没有装饰器
对象.boud_method()
(具有自动传参的效果)
非绑定的方法:用装饰器@staticmethod
不与类或对象绑定,用类或对象都可以调用并且其没有传值的说法。
注意:要与绑定到对象的方法区分开,在类中直接定义的函数没有被任何装饰器装饰的都是绑定对象的方法并且可以自动传值,而用staticmethod装饰的方法不管是类还是对象都没有自动传值的说法。
举例如下:
class foo: def f1(self): print('f1') @classmethod def f2(self): print('f2') @staticmethod def f3(self): print('f3') obj=foo() obj.f1() #绑定到对象 foo.f2() obj.f2()#绑定到类 foo.f3(1) obj.f3(1)#非绑定