面向过程:一种编程思想
在编写代码时 要时刻想着过程这个两个字
过程指的是什么? 解决问题的步骤 流程,即第一步干什么 第二步干什么,
其目的是将一个复杂的问题,拆分为若干的小的问题,按照步骤一一解决,
也可以说 将一个复杂的问题,流程化(为其制定一个固定的实现流程),从而变得简单化
例如:要将大象装进冰箱
打开冰箱
装进大象
关闭冰箱门
以上实现方式 是面向过程的实现方式
面向过程编程优缺点:
优点:复杂的问题,简单化,
缺点:由于其实现流程是固定的,一旦中间某一个步骤发生了修改,将导致整体都需要修改
牵一发动全身.解释:本来有一个实现某个功能的固定的流程,后来需要在原来的基础上增加新的功能,这时候得全部重新设计一遍
扩展性差,维护性差
例如工厂里流水线,一旦中间某个岗位出来问题,整体就无法正常运行,第一个没做完,第二个做不了
使用场景:对扩展性要求较低的软件,比如系统内核,脚本程序(运维工程师写的程序,其目的就是安装一堆软件),Apache HTTP服务器
面向对象:一种编程思想,即编写代码的方式方法
OOP,是Object oriented Programming的简称
将程序看做是一堆对象的集合,实现功能的方式就是对象之间交互来实现
例如:要开一家公司
1.雇个财务
2.雇个人事主管
3.雇几个伙计
4.雇个秘书
5.给他们下达命令
以上方式不是面向过程,为什么?因为其不关系 财务如何算账,也不关心人事如何招人,只关心给他们下达命令
而是面向对象是: 财务,人事主管,几个伙计,秘书
面向对象的优缺点:
优点:
1.不用考虑繁琐的实现步骤,从一个操作工,变成了老板
2.扩展性高了,当需要一个新功能时,搞一个具备新功能的对象,命令它去完成任务
3.各个对象之间的耦合度低,当一个一个对象出现了问题,不会对其他对象产生影响
4.可维护性高
缺点:
1.面向对象的复杂度比面向过程高
2.无法预知执行结果,就像lol的游戏过程,一定不能把过程写死,每个英雄的行为是不固定的
使用场景:需要较高的扩展性时,(直接与用户发生交互的程序例如,qq微信),对于不需要扩展的程序而言,使用面向对象反而增加了复杂度
面向对象编程的本质,就是使用不同的对象来完成程序
面向对象思想中最核心的概念就是 类与对象
什么是对象?
一切皆对象
对象指的是,具备某些特征与技能的结合体,是实实在在存在的具体物体(描述完我就能找到它)
什么是类?
类就是类型,类别,分类
类是一个抽象概念,不是实际存在的,是根据一些具备相同特征和技能的对象抽取得到的,比如说人类.类的作用是用于标识对象与对象之间的差异,通过类就能大致了解一个对象的特征和行为
类与对象之间的关系
类包含了一系列相同特征和技能的对象
对象是属于某个类的实例
先有类还是先有对象?
在生活中是先有对象再根据对象的特征和技能 得到一个类型
在程序中先有类还是先有对象
程序员在程序中相当于上帝 需要什么就创造什么
先有类 才能通过类来产生对象,要先确定对象具备什么特征和什么行为才能产生对象
在计算机创建一个人类对象
要得到对象,必须先告诉计算机,这个对象具备什么特征和行为,所以需要先定义类
class Person: #注类名要按照大驼峰的方式来书写 ThisIsPerson 每个单词的首字母都大写
name='herny'
age='29'
sex='man' #在类中描述对象的特征和行为
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:
school='Marquette'
number='3'
name='Wade'
sex='man'
age='36'
# 创建了两个学生对象
stu1=Student()
stu2=Student()
# 每个对象内存地址都是不同的 , 在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去
print(stu1)
print(stu2)
# 由于name的值是声明在类中的,所以每个对象使用的都是同一个值
print(stu1.name)
print(stu2.name)
# 为对象单独制定属性
stu1.name='James'
stu2.name='Bosh'
print(stu1.name)
print(stu2.name)
# 通过__dict__可以获取一个对象中包含的内容
print(stu1.__dict__)
print(stu2.__dict__)
# 获取类中包含的内容
print(Student.__dict__)
在计算机创建一个人类对象
要得到对象,必须先告诉计算机,这个对象具备什么特征和行为,所以需要先定义类
class Person: #注类名要按照大驼峰的方式来书写 ThisIsPerson 每个单词的首字母都大写
name='herny'
age='29'
sex='man' #在类中描述对象的特征和行为
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:
school='Marquette'
number='3'
name='Wade'
sex='man'
age='36'
# 创建了两个学生对象
stu1=Student()
stu2=Student()
# 每个对象内存地址都是不同的 , 在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去
print(stu1)
print(stu2)
# 由于name的值是声明在类中的,所以每个对象使用的都是同一个值
print(stu1.name)
print(stu2.name)
# 为对象单独制定属性
stu1.name='James'
stu2.name='Bosh'
print(stu1.name)
print(stu2.name)
# 通过__dict__可以获取一个对象中包含的内容
print(stu1.__dict__)
print(stu2.__dict__)
# 获取类中包含的内容
print(Student.__dict__)
"属性的访问顺序"
1.当对象中不存在这个属性时会到类中去找
2.如果对象中存在这个属性,优先访问对象中的属性
查找顺序为 对象 -> 类
class Student:
name='Wade'
age='18'
sex='man'
stu1=Student()
print(stu1.name)
stu1这个对象中没有数据,就回到类Student里面去找.
结果:Wade
class Student:
name='Wade'
age='18'
sex='man'
stu1=Student()
stu1.name='James'
print(stu1.name)
对象中存在这个属性,所以直接取对象中的数据
结果:James
当创建一个类的时候 会产生名称空间,存储类中名称和值的绑定关系
当创建一个对象的时候 会产生名称空间,存储对象中名称和值的绑定关系
类还有另一个作用 就是 作为对象的模板,所有属于同一个类的对象,都具备类中的公共内容
即使我们什么都不写 类中也存在一些自带的属性,是从父类得到的(继承会详细讨论)
class Student:
pass
stu1=Student()
stu2=Student()
#指定属性
stu1.name='Wade'
stu1.age='36'
stu1.sex='man'
stu2.name='Wendy'
stu2.age='24'
stu2.sex='woman'
print(stu1.name)
print(stu2.age)
有上述方法太繁琐,于是我们建立函数来解决,创建这个函数目的是用于设置对象的属性 ,如果没有对象则该函数没有存在的意义,也就是初始化函数与类应该是一个整体,应该讲这个函数放到类中.
class Student():
def msg(obj,name,age,sex):
obj.name=name
obj.age=age
obj.sex=sex
stu1=Student()
Student.msg(stu1,'Wade',36,'man')
print(stu1.name)
现在已经简化了代码 但是对象的创建和初始化步骤是分开的, 通常对象一旦创建 就应该进行初始化,所以最好时将创建与初始化进绑定
作为一个人 一旦出生 性别必须要指定
# 带有__开头__结尾的函数 是一些特殊内置函数,会在某个时间点自动触发执行
class Person:
# 初始化函数名称是固定 该函数会在调用类是时自动执行,self参数必须有,表示要进行初始化的对象,系统会自动传值
def __init__(self,name,age):
print('执行了__init__')
print(self)
self.name=name
self.age=age
p1=Person('henry',29)
print(p1.__dict__)
# init 函数用于初始化对象,它会在创建对象时,自动执行,并传入调用类时传递的参数,第一个参数表示要初始化的对象本身.
# self(第一个)参数不需要手动传递
# self表示对象自己 是一个形式参数,名字可以随便取,但是不建议修改
小练习: 有一个Dog类 每一个Dog对象都应该会叫 会跑 请用面向对象来完成
class Dog():
def __init__(self,dogname,gender,age):
self.dogname=dogname
self.gender=gender
self.age=age
def call(self):
print('你们听%s又叫了'%self.dogname)
def run(self):
print('你们看%s又跑了'%self.dogname)
dog1=Dog('皮皮','公','3')
dog2=Dog('科科','母','2')
dog1.run()
dog2.call()
1.绑定方法是什么?
什么是绑定 把两个东西捆绑在一起
什么是方法 方法 就是 函数
函数是专业术语,不好理解,面向对象编程思想,是要我们模仿现实生活中的抽象概念,为了方便理解就把函数称之为方法.
绑定方法就是 把对象与函数进行绑定
对象本质上就是一种存放数据的容器
函数是用于处理数据的代码
绑定方法就是将数据与处理数据的函数绑定在一起
2.为什么要把把对象与函数进行绑定?
name = "henry"
age = 29
sex = "男"
name2 = "wendy"
age2 = 24
sex2 = "女"
def show_info(name,age,sex):
print("hello i am %s my age:%s my sex:%s" % (name,age,sex))
show_info(name2,sex2,age2)
show_info(name,sex,age)
第一个问题传递参数,必须手动传递,很有可能传参顺序而发生错误
第二个问题每次处理数据 都需要手动传参数
第三个问题 当要处理的数据特别的多 就不能再定义为变量了 你可以使用列表出来存储要处理的数据
但是 每次处理 都需要先获取数据 在传递给处理数据的函数
所以将 要处理的数据与 处理数据的函数进行绑定
调用函数 就变成了调用对象的方法
默认情况下 在类中定义的函数都是绑定方法,共同点是,都会将对象作为第一个参数self
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))
stu1 = Student("zion","man",18)
stu1.sayHI()
当用用对象来调用类中的方法时,默认把对象传入方法中
Student.sayHI(stu1)
而用类名来调用时,则需要手动传入对象
只要拿到对象 就同时拿到了数据和处理数据的方法
3.绑定方法分为两种 一种是绑定给对象的,一种绑定给类的
class Student:
school = "beijing"
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
绑定给类的:
绑定给类的方法使用一个装饰器叫classmethod,必须有一个参数,表示当前类,参数名也可以自己定义,建议不要修改
@classmethod
def print_school_name(cls): # 输出类里面叫school的属性
print(cls.school)
绑定给对象的:
def say_hi(self):
print(self.name, " 说: 你好")
Student.school_msg()
#类的绑定方法,对象和类都能调用,并且都会自动传入这个类
stu1=Student('irene','27','woman')
Student.say_hi(stu1)
# 对象绑定方法 可以使用对象来调用 也可以使用类名来调用
# 在对象调用时会自动传入对象自己
# 类调用时不会自动传参
一个方法到底应该绑定给对象还是绑定给类?
当要处理的数据包含在类中时,就应该绑定给类
当要处理的数据包含在对象中时,就应该绑定给对象
总结:
"""
# 类的绑定方法和对象的绑定方法的相同与不同
相同点:
1.都会自动传值
2.都可以被类和对象调用
不同点:
1.对象绑定方法再对象调用时 传的是对象自己 而类绑定方法字自动传的是类自己
2.第一个参数 个cls 一个叫self
为什么要绑定?
# 第一个问题传递参数,必须手动传递,很有可能传参顺序而发生错误
# 第二个问题每次处理数据 都需要手动传参数
# 第三个问题 当要处理的数据特别的多 就不能再定义为变量了 你可以使用列表出来存储要处理的数据
但是 每次处理 都需要先获取数据 在传递给处理数据的函数
之所以绑定 ,简化代码,提高效率
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("wendy","woman")
t1.test_func(100)
print(t1.test_func)
# 什么是非绑定方法 在类中 即不绑定给类 也不绑定给对象
# 特点:没有自动传参数的效果 ,类和对象向都能调用,就是一个普通函数
# 当你的这个功能不需要访问类的数据 也不需要访问对象的数据,就可以作为一个非绑定方法
# 使用场景较少
小练习:
1.创建Student类
2.拥有以下属性: 姓名 性别 年龄 学校 班级
3.拥有以下方法
save(name) 其作用是将这个对象序列化到文件中
get_obj(name) 其作用是根据name从文件中反序列化为得到一个对象
分析save方法和get_obj 应该作为绑定给对象还是绑定给类
import json
class Student:
school='pking'
def __init__(self,name,sex,age,classes):
self.name=name
self.sex=sex
self.age=age
self.classes=classes
def save(self):
dic={'name':self.name,'age':self.age,'sex':self.sex,'classes':self.classes}
with open(self.name,'wt',encoding='utf-8') as f:
json.dump(dic,f)
@classmethod
def get_obj(cls,name):
with open(name,'rt',encoding='utf-8') as f:
dic=json.load(f)
obj=cls(dic['name'],dic['sex'],dic['age'],dic['classes'])
return obj
# stu1=Student('henry','man','29','python五期')
# stu1.save()
stu1=Student.get_obj('henry')
print(stu1.name)