面向对象
一:面向过程
是一种编程思想。将一个复杂的问题流程化(为其制定一个固定的实现流程),从而变得简单化
优点:复杂的问题简单化
缺点:由于实现流程固定,一旦中间步骤发生了修改,将导致整体都需要修改
牵一发而动全身,扩展性差,维护性差
使用场景:对扩展性要求较低的软件,比如系统的内核,脚本程序(比如运维工程师写的程序,其目的就是安装一个程序)Apache HTTP服务器
二:面向对象(OOP:Object Oriented Programing的简称,就是面向对象的缩写)
是一种编程思想,即编写代码的方式方法。将程序看作是一堆对象的集合,实现功能的方式就是对象之间交互来实现。
面向对象思想中最核心的概念就是:类和对象
1.什么是对象?
一切皆对象
对象指的是,具备某些特征和技能的结合体,是实实在在存在的具体物体(描述完之后就能立刻找到对应的物体)
2.什么是类?
类就是类型、对象
类是一个抽象概念,不是实际存在的,是根据一些具备相同特征和技能的对象抽取得到的,比如说人类。
类的作用:用于标识对象与对象之间的不同,通过类就能大致了解一个对象的特征和行为
类与对象之间的关系:
类包含了一系列相同特征和技能的对象
对象属于某个类的实例
3.先有类还是先有对象?
在生活中先有对象再根据对象的特征和技能得到一个类型,但是,在程序中先有类,才能通过类来产生对象,要先确定具备什么特征和什么行为才能产生对象。
优点:
1.不用考虑繁琐的实现步骤,从一个操作工变成了boss
2.扩展性高,当需要一个新功能时,添加一个具备新功能的对象,命令他去完成任务
3.各个对象之间耦合度低,当一个对象出现问题不会对其他对象产生影响
4.可维护性高
缺点:
1.面向对象的复杂度比面向过程高
2.无法预测执行结果,就像LOL游戏过程,一定不能把过程写死,每个英雄的行为都是不固定的
4.使用场景
当需要较高的扩展性时(直接与用户发生交互的程序例如qq,微信)
对于不需要扩展的程序而言,使用面对对象反而增加了复杂度
面向对象编程的本质就是使用不同的对象来完成程序。
5.使用方法
注意:类名要按照大驼峰的方式来书写(ThisIsPerson每个单词的首字母都大写)
在类中描述对象的特征和行为:
class Person: # 用变量来描述特征 name = "李四" sex = "man" age = 20 # 得到对象 通过调用类 ,也称之为实例化 或 创建对象 obj = Person() print(obj) #<__main__.Person object at 0x00000279452B7C50> # 模块名为main 其包含一个Person类 通过Person类产生了一个对象 地址为0x00000279452B7C50 # 这是一个Person类的对象 其地址为0x00000279452B7C50 # 使用对象的属性(说的就是特征) print(obj.name) print(obj.age) print(obj.sex)
class Student: name = "盖伦" sex = "man" age = 18 # 学生的学校 由于每个学生的学校都是相同 所以将其放到类中 school = "Tsinghua" # 创建了两个学生对象 stu1 = Student() stu2 = Student() print(stu1) print(stu2) # 每个对象内存地址都是不同的 , 在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去 print(id(stu1.name)) print(id(stu2.name)) # 由于name的值时声明在类中的,所以每个对象使用的都是同一份 print(stu1.name) print(stu2.name) # 为对象单独制定属性 stu1.name = "韩信" stu2.name = "陈大炮" print(stu1.name) print(stu2.name) # 每个对象的name属性都不同,则意味需要给每个对象单独指定name # 存储属性的位置有两个 一个是类中,还有一个对象中 # 当每个对象的某个特征都相同时则放到类中 # 当每个对象的某个特征都不同时则放到对象中 # 通过__dict__可以获取一个对象中包含的内容 stu1.age = 30 print(stu1.__dict__) print(stu2.__dict__) # 获取类中包含的内容 print(Student.__dict__)
6.属性的访问顺序
当对象中不存在时会到类中去查找,如果对象中存在这个属性,优先访问对象中的属性。
查找顺序为:对象——>类
当创建一个类的时候,会产生名称空间,存储类中名称和值的绑定关系。
当创建一个对象的时候,会产生名称空间,存储对象中名称和值的绑定关系。
类还有另一个作用,就是:作为对象的模板,所有属于同一类的对象,都具备类中的公共内容。
即使我们什么都不写,类中也存在一些自带的属性,是从父类得到的。
7.初始化函数
init用于初始化对象,它会在创建对象时,自动执行,并传入调用类时传递的参数,第一个参数表示要初始化的对象本身。
self(第一个)参数不需要手动传递
self表示对象自己,是一个形式参数,名字可以随便取,但是不建议修改。
# 作为一个人 一旦出生 性别必须要指定 # 带有__开头__结尾的函数 是一些特殊内置函数,会在某个时间点自动触发执行 class Person: # 初始化函数名称是固定 该函数会在调用类是时自动执行,self参数必须有,表示要进行初始化的对象,系统会自动传值 def __init__(self,name,age): self.name = name self.age =age p1 = Person("小仙女",18) p2 = Person("张艺兴",20) print(p1.__dict__) print(p2.__dict__)
8.绑定方法
绑定方法就是把对象和函数进行绑定。那么,调用函数就变成了调用对象的方法。
对象本质上就是一种存放数据的容器,函数就是用于处理数据的代码,绑定方法就是将数据与处理数据的函数绑定到一起
class Student: school = "BeiJing" def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def learning(self): print("正在学习..") def sayHI(self): print("hello my name is %s my age:%s my sex:%s" % (self.name,self.age,self.sex)) # 默认情况下 在类中定义的函数都是绑定方法,共同点是,都会将对象作为第一个参数self stu1 = Student("一个学生","man",18) stu1.sayHI() Student.sayHI(stu1) # 当用对象来调用类中的方法时,默认把对象传入方法中 # 而用类名来调用时,则需要手动传入对象 print(stu1.sayHI) #<bound method Student.sayHI of <__main__.Student object at 0x000001784F889C50>> # 这是一个绑定方法,本质上是Student类中的sayHI函数 现在把这个函数绑定给了地址为0x000001784F889C50的对象 stu2 = Student("李四","女",19) stu2.sayHI() print(stu2.sayHI)
只要拿到对象,就同时拿到了数据和处理数据的方法。
为什么要绑定?
问题一,传递参数必须手动传递,很有可能在传参顺序发生错误
问题二,当要处理的数据特别多时就不能再定义为变量了,你可以使用列表存储需要处理的数据,但是每次处理都需要先获取数据,再传递给处理数据的函数。所以要将处理的数据与处理数据的函数进行绑定。简化代码,提高效率。
class Student: school = "beijing" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex #绑定方法分为两种 一种是绑定给对象的,一种绑定给类的。 # 绑定给类的方法 使用一个装饰器叫classmethod,必须有一个参数,表示当前类,参数名也可以自己定义,建议不要修改 # 这是绑定给类的方法 @classmethod def print_school(cls): # 输出类里面叫school的属性 print(cls.school) # 这是绑定给对象的方法 def sayHello(self): print(self.name, " 说: 你好")
类的绑定方法,对象和类都能调用,并且能够自动传入这个类
Student.print_school() #类的调用
stu1 = Student("印度阿三","woman",20) #对象的调用
stu1.print_school()
注意:
对象绑定方法可以使用对象来调用,也可以使用类名来调用,在对象调用时会自动传入对象自己,类调用时不会自动传参。
当要处理的数据包含在类中时,就应该绑定给类。当要处理的数据包含在对象中时,就应该绑定给对象。
# 有一个Dog类 每一个Dog对象都应该会叫 会跑 请用面向对象来完成 class Dog: def __init__(self,nikename,gender,age): self.nikename = nikename self.gender = gender self.age = age def run(self): print("不好了 ",self.nikename,"跑了 ") def bark(self): print("听",self.nikename,"在瞎叫...") d1 = Dog("大金毛","母的",2) d2 = Dog("大黄","公的",3) d1.run() d2.bark()
类的绑定方法和对象的绑定方法的相同与不同:
相同点:
1.都会自动传值
2.都可以被类和对象调用
不同点:
1.对象绑定方法在对象调用时,传的是对象自己,而类绑定方法中传的是类自己
2.第一个参数,一个叫cls,一个叫self
9.非绑定方法
在类中,即不绑定给类也不绑定给对象。
特点:
没有自动传入参数的效果,类和对象都能调用,就是一个普通函数。但是当你的这个功能不需要访问类的数据,也不需要访问对象的数据,就可以作为一个非绑定方法。
class Teacher: def __init__(self,name,sex): self.name = name self.sex = sex # @staticmethod 用于定义个非绑定方法 @staticmethod def test_func(num): print("test_func run!") print(num) Teacher.test_func(1) t1 = Teacher("矮根","男") t1.test_func(100) print(t1.test_func)