面向对象
---恢复内容开始---
一、面向对象
核心“对象”二字,对象指的是 特征与技能的结合体,
基于该思想编写程序就好比在创造一个世界,你就是这个世界的上帝,是一种上帝式的思维方式。
优点:可扩展性强
缺点:编程的复杂度高于面向过程
二、类
一 :类
对象是特征与技能的结合体, 那类就是一系列对象相同的特征与技能的结合体
2、在现实世界中 现有对象 ,再由对象总结出类, 对象是具体存在的, 而类只是 一种抽象的概念。
3、而在程序中,务必保证:先定义类,后调用类来产生对象
定义一个学生类:
class OldboyStudent: school = "oldboy" # 用变量表示特征 def learn(self): # 用函数表示技能 print("is learning....") def choose(self): # 用函数表示技能 print("choose course...")
注意 :在定义类的阶段会立刻执行类体内的代码,然后将产生的名字存放于类名称空间中,
调用类, 产生程序中的对象。
有以下属性:
首先定义类 class People: country ="China" def run(self): print(‘----》’,self) #查看 People.country People.run #增加 People.x=1 #修改 People.country="CHINA" #删除 del People.x
不过需要强调的是:
1、类中最常见的就是变量与函数的定义, 但并不是说一定要定义出变量与函数
2、程序中的类并不完全等同于显示世界中的类
__init__方法
强调:
1、该方法内可以有任意的Python代码
2、一定不能有返回值
绑定方法
1、绑定给谁, 就应该由谁来调用
2、谁来调用就会将谁当做第一个参数传入
一切皆是对象
在面向对象中 ,一切皆是对象
1、继承:
继承是一种新建类的方式,新建的类成为子类或派生类
父类成为基类或者超类
在python中的继承支持一个子类可以同时继承多个父类
语法:
class ParentClass1: pass class ParentClass2: pass class Subclass1(ParentClass1): #Subclass1为子类 parentClass1 为父类 pass class Subclass2(ParentClass1,ParentClass2): #Subclass2为子类 parentClass1 parentClass2为父类
2、新式类与经典类:
新式类:
继承object 的类及其子类都是新式类
在python3中如果一个类没有继承任何父类,那么默认继承object类,即在python3中所有的类都是新式类
经典类:(只有在python2中才有)
没有继承object的类及其子类 都是经典类
二者的区分:
主要体现在菱形继承下查找:
经典类:深度优先查找
新式类:广度优先查找
3、如何查找继承关系:
先抽象
抽象对象之间相似之处得到了类
再总结类与类之间的相似得到父类
再继承
子类继承父类, 子类可以遗传父类的属性
4、属性的查找:
obj.x
1、先从obj.__dict__
2、对象的类.__dict__
3、父类.__dict__
5、派生
派生:子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类)
如果与父类同名,以子类自己的为准
在子类派生出的新方法中重用父类的功能
有两种方式:
(1)指名道姓的调用(其实与继承没有什么关系的)
class OldboyPeople: school='oldboy' def __init__(self,name, age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): print(""" ==========个人信息========== 姓名:%s 年龄:%s 性别:%s """ %(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): # self.name=name # self.age=age # self.sex=sex OldboyPeople.__init__(self,name,age,sex) self.level=level self.salary=salary def tell_info(self): OldboyPeople.tell_info(self) print(""" 等级:%s 薪资:%s """%(self.level,self.salary)) tea1 = OldboyTeacher('egon',18,'male',9,3.1) print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary)
(2)super()调用 (严格依赖于继承)
super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性
class OldboyPeople: school="oldboy" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): print(''' ======个人信息===== 姓名:%s 年龄:%s 性别:%s ''' %(self.name,self.age,self.sex)) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): super().__init__(name,age,sex) self.level=level self.salary=salary def tell_info(self): super().tell_info() print(''' 等级:%s 薪资:%s '''%(self.level,self.salary)) tea1=OldboyTeacher('egon',18,"male",9,3.1) tea1.tell_info()
6、组合
作用:
组合与继承的作用一样,都是用来减少类 与类之间的重复代码
定义:
A 类的对象具备某一个属性, 该属性的值是B类的对象,基于这种方式就把A 类与B类组合到一起
对象既能使用A类中的数据与功能, 也能使用B类中的数据与功能。
7、封装
封装就是隐藏,隐藏指的是在类内部将一个属性藏起来
让类外部的使用者无法直接用到, 在py中就是用__开头将一个属性藏起来。
调用的时候 创建一个接口,通过接口调用
class People: def __init__(self,name): #将name隐藏起来 self.__name=name def tell_name(self): # 创建一个接口 供外部调用 return self.__name obj=People('egon') obj.tell_name()
8:
(1) property 用来将类内的函数伪装成一个数据属性
可以通过 . 来调用
class Foo: @property def name(self): pass @name.setter def name(self,value): pass @name.deleter def name(self): pass obj=Foo obj.name
(2) classmethod
将类中的一个函数绑定给类,调用的时候将类本身作为第一个参数 自动传进去
(3) staticmethod 将类中的一个函数解除绑定
9 多态与多态性
多态:同一种事物有多种形态 ,在程序中用继承可以表现出多态
多态性:可以在不考虑对象的具体的类的情况下直接参考基类的使用对象。
10 反射
python中的反射:通过字符串的形式操作对象的相关属性。python中的一切事物都是对象(都可以使用反射)
11、__setattr__, __delattr__, __getattr__
class Foo: x=1 def __init__(self,y): self.y=y def __getattr__(self, item): print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value): print('----> from setattr') # self.key=value #这就无限递归了,你好好想想 # self.__dict__[key]=value #应该使用它 def __delattr__(self, item): print('----> from delattr') # del self.item #无限递归了 self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行 f1=Foo(10) print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 f1.z=3 print(f1.__dict__) #__delattr__删除属性的时候会触发 f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 del f1.a print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发 f1.xxxxxx
---恢复内容结束---