一.什么是面向对象的程序设计为什么要有它

1.面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的编程就好比设计一条流水线,是一种机械式的思维方式。

优点是:复杂的问题流程化,进而简单化

缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux内核,git,以及Apache HTTP Server等


2.面向对象的程序设计:核心是对象二字,对象是特征与技能的结合体,基于面向对象设计程序就好比在创造一个世界,你就是这个世界的上帝,存在的皆为对象,不存在的也可以创造出来,与面向过程的思维方式形成鲜明的对比,面向对象更加重视对现实世界的模拟,是一种“上帝式”的思维方式

优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反应在整个体系中。

缺点是:编程复杂度远高于面向过程

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方


二.类与对象

类:对象是特征与技能的结合体,而类则是一系列对象相同的特征与技能的结合体

强调:

1.对象是具体存在的事物,而类则一个抽象的概念

2.站在不同的角度总结出的类与对象是不同的

在现实世界中:先有一个个具体存在的对象,然后随着人类文明的发展才总结出类的概念

在程序中: 先定义类,后调用类来产生对象

1.先定义类classOldboyStudent:#相同的特征school='oldboy'#相同的技能defchoose_course(self):print('choosingcourse')#类是一系列对象相同的特征(变量)与技能(函数)的结合体,即类体中最常见的就是变量与函数的定义#但其实类体中是可以存在任意python代码的#类体代码会在类定义阶段立即执行,会产生一个类名称空间,用来将类体代码执行过程中产生的名字都丢进去,查看方式如下#print(OldboyStudent.__dict__)#查看类的名称空间#print(OldboyStudent.school)#print(OldboyStudent.__dict__['school'])#print(OldboyStudent.choose_course)#OldboyStudent.school='OLDBOY'#OldboyStudent.__dict__['school']='OLDBOY'#OldboyStudent.country='China'#OldboyStudent.__dict__['country']='China'#delOldboyStudent.country#delOldboyStudent.__dict__['country']#print(OldboyStudent.__dict__)#总结:#1.类本质就是一个名称空间,或者说是一个用来存放变量与函数的容器#2.类的用途之一就是当做名称空间从其内部取出名字来使用#3.类的用途之二是调用类来产生对象2.后调用类来产生对象#s1=OldboyStudent()#s2=OldboyStudent()#s3=OldboyStudent()#如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值classOldboyStudent:......def__init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sex......s1=OldboyStudent('李坦克','男',18)#先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18)s2=OldboyStudent('王大炮','女',38)s3=OldboyStudent('牛榴弹','男',78)#程序中对象的用法#执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间s2.__dict__{'name':'王大炮','age':'女','sex':38}s2.name#s2.__dict__['name']s2.name='王三炮'#s2.__dict__['name']='王三炮's2.course='python'#s2.__dict__['course']='python'dels2.course#s2.__dict__.pop('course')

!!!细说_init__方法!!!

#方式一:为对象初始化自己独有的特征classPeople:country='China'x=1defrun(self):print('----->',self)#实例化出三个空对象obj1=People()obj2=People()obj3=People()#为对象定制自己独有的特征obj1.name='egon'obj1.age=18obj1.sex='male'obj2.name='lxx'obj2.age=38obj2.sex='female'obj3.name='alex'obj3.age=38obj3.sex='female'#print(obj1.__dict__)#print(obj2.__dict__)#print(obj3.__dict__)#print(People.__dict__)#方式二、为对象初始化自己独有的特征classPeople:country='China'x=1def__init__(obj,x,y,z):#obj=obj1,x='egon',y=18,z='male'obj.name=xobj.age=yobj.sex=zdefrun(self):print('----->',self)obj1=People('egon',18,'male')#People.__init__(obj1,'egon',18,'male')obj2=People('lxx',38,'female')#People.__init__(obj2,'lxx',38,'female')obj3=People('alex',38,'female')#People.__init__(obj3,'alex',38,'female')#__init__方法#强调:#1、该方法内可以有任意的python代码#2、一定不能有返回值classPeople:country='China'x=1def__init__(obj,name,age,sex):#obj=obj1,x='egon',y=18,z='male'#iftype(name)isnotstr:#raiseTypeError('名字必须是字符串类型')obj.name=nameobj.age=ageobj.sex=sexdefrun(self):print('----->',self)#obj1=People('egon',18,'male')#obj1=People(3537,18,'male')#print(obj1.run)#obj1.run()#People.run(obj1)#print(People.run)!!!__init__方法之为对象定制自己独有的特征

三.属性查找

类有两种属性:数据属性和函数属性

1.类的数据属性是所有对象共享的

2.类的函数属性是绑定给对象用的

#类的数据属性是所有对象共享的,id都一样print(id(OldboyStudent.school))print(id(s1.school))print(id(s2.school))print(id(s3.school))**************4377347328437734732843773473284377347328**************#类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样#ps:id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准print(OldboyStudent.learn)print(s1.learn)print(s2.learn)print(s3.learn)*******************<functionOldboyStudent.learnat0x1021329d8><boundmethodOldboyStudent.learnof<__main__.OldboyStudentobjectat0x1021466d8>><boundmethodOldboyStudent.learnof<__main__.OldboyStudentobjectat0x102146710>><boundmethodOldboyStudent.learnof<__main__.OldboyStudentobjectat0x102146748>>*******************

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

四.绑定到对象的方法的特殊之处

#改写classOldboyStudent:school='oldboy'def__init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sexdeflearn(self):print('%sislearning'%self.name)#新增self.namedefeat(self):print('%siseating'%self.name)defsleep(self):print('%sissleeping'%self.name)s1=OldboyStudent('李坦克','男',18)s2=OldboyStudent('王大炮','女',38)s3=OldboyStudent('牛榴弹','男',78)

类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数

OldboyStudent.learn(s1)#李坦克islearningOldboyStudent.learn(s2)#王大炮islearningOldboyStudent.learn(s3)#牛榴弹islearning

类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法

强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)