面向对象
面向过程
核心是过程,过程指的是问题的解决步骤,即先干什么再干什么,基于面向过程去设计程序就好比设计一条流水线,是一种机械式的思维方式
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差
面向对象
核心是对象,对象就是特征与技能的结合体,如果把设计程序比喻成创造一个世界,那你就是这个世界的上帝,与面向过程对机械流水线的模拟形成鲜明的对比,
面向对象更加注重的是对现实世界的模拟
优点:可扩展性高
缺点:极易出现过度设计
类
一系列对象相似的特征与技能的结合体
在现实世界中,先有一个个具体存在的对象,随着发展,总结相似之处,得到现实中的类
在程序中,一定是先定义类,后调用类来产生对象
第一阶段:由现实中的对象,总结出现实中的类
obj1: 特征 学校=oldboy 名字=李 年龄=18 性别=女 技能 学习 吃饭 obj2: 特征 学校=oldboy 名字=张 年龄=28 性别=男 技能 学习 吃饭 obj3: 特征 学校=oldboy 名字=牛 年龄=18 性别=女 技能 学习 吃饭
类就是现实中的老男孩学生类:
相似的特征 学校=oldboy 相似的技能 学习 吃饭
第二阶段:程序中的类产生程序中的对象
class OldboyStudent: # 定义了类,类体中的代码在类定义阶段就会执行 school = 'oldboy' # 特征 ,类的数据属性 def learn(self): # 技能,类的函数属性 print('is learning') def eat(self): print('is eating') print(OldboyStudent.__dict__) # 查看类的 名称空间(用来存放类中的变量名和函数名) #通过字典访问里面的属性 print(OldboyStudent.__dict__['school']) print(OldboyStudent.__dict__['learn']) #python提供了访问属性的语法 print(OldboyStudent.school) print(OldboyStudent.learn) OldboyStudent.learn(123) #新增属性 OldboyStudent.x=11111 OldboyStudent.school='Oldboy' print(OldboyStudent.__dict__) #删除属性 del OldboyStudent.school print(OldboyStudent.__dict__)
对象
如何产生程序中的对象?类名加括号,调用类,产生一个该类的实际存在的对象,该过程称为实例化,产生的结果又可以称为实例
obj1=OldboyStudent() obj2=OldboyStudent() obj3=OldboyStudent()
产生了3个相同的对象,因为并没有使用__init__()
class OldboyStudent: school = 'oldboy' def __init__(self,name,age,sex): # 只在实例化的时候执行,在对象产生之后才会执行 if not isinstance(name,str): raise TypeError('名字必须是字符串类型') self.name=name self.age=age self.sex=sex def learn(self): print('%s is learning' % self.name) def eat(self): print('is eating') obj1=OldboyStudent('李',18,'女') #两步:1.先生成一个空对象 2.连同空对象和后面的三个参数,组成一组(obj1,'李',18,'女')传给__init__(),相当于 OldboyStudent.__init__(obj1,'李',18,'女') print(obj1.name) # obj1.__dict__['name'] obj1.name='网' print(obj1.name) print(obj1.school,id(obj1.school)) print(obj2.school,id(obj2.school)) print(obj3.school,id(obj3.school)) print(OldboyStudent.school,id(OldboyStudent.school)) #以上4个完全相同,就是同一个 #对象可以访问类的数据属性,类的数据属性是共享给所有对象使用的,id都一样 #类的函数属性 OldboyStudent.learn(obj1) print(obj1.learn) #绑定方法 print(OldboyStudent.learn) # 函数属性 obj1.learn() # OldboyStudent.learn(obj1) #绑定方法的特殊之处在于,绑定给谁,就由谁来调用,谁来调用,就把谁当作第一个参数传入
统计
class Foo: count=0 def __init__(self,x,y,z): self.x=x self.y=y self.z=z Foo.count+=1 obj1=Foo(1,1,1) obj2=Foo(1,2,1) obj3=Foo(1,2,3) print(obj1.count)
print(Foo.count)
对象之间的交互
class Garen: camp='Demacia' def __init__(self,nickname,life_value=100,aggresivisity=80): self.nickname=nickname self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Riven: camp='Noxus' def __init__(self,nickname,life_value=80,aggresivisity=100): self.nickname=nickname self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity g1=Garen('草丛') r1=Riven('兔') print(r1.life_value) g1.attack(r1) print(r1.life_value)
继承
1.解决代码重用问题
2.继承是类与类之间的关系,是一种,什么是什么的关系
3.在子类派生出新的方法内重用父类功能的方式:指名道姓法
OldboyPeople.__init__()
这种调用方式本身与继承没有关系
class ParentClass1: pass class ParentClass2: pass class SubClass1(ParentClass1): pass class SubClass2(ParentClass1,ParentClass2): pass print(SubClass1.__bases__) print(SubClass2.__bases__)
print(ParentClass1.__bases__) #python3的基类默认继承object,这是经典类与新式类的区别 #查看父类
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def eat(self): print('is eating') class OldboyStudent(OldboyPeople): def learn(self): print('%s is learning' % self.name) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,salary,title): OldboyPeople.__init__(self,name,age,sex): self.salary=salary self.title=title def teach(self): print('%s is teaching' % self.name) obj1=OldboyStudent('tom',23,'female') egon_obj=OldboyTeacher('egon',23,3000,'沙河讲师')
组合
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def eat(self): print('is eating') class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,salary,title): OldboyPeople.__init__(self,name,age,sex) self.salary=salary self.title=title self.course=[] def teach(self): print('%s is teaching' % self.name) class Course: def __init__(self,course_name,course_period,course_price): self.course_name=course_name self.course_period=course_period self.course_price=course_price def tell_info(self): print('<课程名:%s 周期:%s 价格:%s>' % (self.course_name,self.course_period,self.course_price)) python=Course('Python','6month',3000) linux=Course('Linux','3month',2000) bigdata=Course('Bigdata','1month',1000) egon_obj=OldboyTeacher('egon',18,'male',3000,'沙河讲师') egon_obj.course.append(python) egon_obj.course.append(linux) for obj in egon_obj.course: obj.tell_info() yl_obj=OldboyStudent('杨',15,'male') yl_obj.course.append(python) for i in yl_obj.course: i.tell_info()
绑定方法与非绑定方法
1.绑定给谁,谁来调用就自动将它本身当作第一个参数传入
2.绑定到对象的方法前面已经写了
绑定到类的方法
#settings.py HOST='192.168.0.1' PORT=3307
import settings import uuid class MySql: def __init__(self,host,port): self.host=host self.port=port self.id=self.create_id() #每产生一个对象就赋予一个唯一的id #def func1():pass #def func2(self):pass #上面两种都是给对象用的,并且def func():pass是一种错误的方法 @classmethod #绑定给类 def from_conf(cls): # cls就是这个类,函数内部的不需要对象,需要的是类 return cls(settings.HOST,settings.PORT) def func1(self): #绑定给对象 pass @staticmethod 和谁都没有关系,就是一个普通函数,工具,不与任何对象绑定 def create_id(): #函数内既不需要类也不需要对象,就定义成非绑定方法 return str(uuid.uuid1()) conn1=MySql('127.0.0.1',3306) #实例化传入 conn2=MySql.from_conf() #配置文件中取出 print(conn1.host,conn2.host) #和对象没有关系就定义成类方法 conn3=MySql('127.0.0.1',3306) conn4=MySql('127.0.0.2',3307) conn5=MySql('127.0.0.3',3308) print(conn3.id,conn4.id,conn5.id)
继承实现原理
单继承
class A: def f1(self): print('A.f1') def f2('A.f2'): print('A.f2') self.f1() # b.f1() class B(A): def f1(self): print('B.f2') b=B() b.f2() #A.f2 #B.f2
多继承
class A: def test(self): print('A') class E: def test(self): print('E') class H: def test(self): print('H') class G(H): def test(self): print('G') class B(A): def test(self): print('B') class D(E): def test(self): print('D') class F(G): def test(self): print('F') class C(B,D,F): def test(self): print('C') print(C.mro()) # 查看C类的继承关系
super()
子类的方法重用父类的功能
class OldboyPeople: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def eat(self): print('is eating') def teach(self): print('这是父类的teach') class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,salary,title): #OldboyPeople.__init__(self,name,age,sex) # 指名道姓,与继承无关 #super(OldboyTeacher,self).__init__() #适用于python2 print(super().school) # oldboy print(super().eat) super().__init__(name,age,sex) self.salary=salary self.title=title def teach(self): #OldboyPeople.teach(self) super().teach() print('%s is teaching' % self.name) print(OldboyTeacher.mro()) egon_obj=OldboyTeacher('egon',18,'male',300,'沙河将讲师') print(egon_obj.title) print(egon_obj.__dict__) egon_obj.teach()
class A: def test(self): super().test() classB: def test(self): print('B') class C(A,B): pass c=C() c.test() #并不会发生报错,因为super是只看C类的mro列表,并不是看到A类的父类object没有test方法就会报错 #B