什么是面向对象:
在介绍面向对象之前,要先明确面向过程
面向过程: 解决问题的步骤、流程,即第一步干什么,第二步干什么,其目的是将一个复杂的问题,拆分为若干的小的问题,按照步骤一一解决,也可以说将一个复杂的问题流程化为其制定一个固定的实现流程,从而变得简单化。
面向过程编程优缺点:
优点:复杂的问题简单化
缺点:由于其实现流程是固定的,一旦中间某一个步骤发生了修改,导致整体都需要修改
面向对象:是一种编程思想,即编写代码的方式方法,是Object oriented Programing的简称,就是面向对象的英文缩写将程序看做是一堆对象的集合,实现功能的方式就是对象之间交互来实现
面向对象编程优缺点:
优点:
不用考虑繁琐的实现步骤,从一个操作工,变成了老板
扩展性高了,当需要一个新功能时,搞一个具备新功能的对象,命令它去完成任务
各个对象之间的耦合度低,当一个一个对象出现了问题,不会对其他对象产生影响
可维护性高
缺点:
面向对象的复杂度比面向过程高
无法预知执行结果,就像lol的游戏过程,一定不能把过程写死,每个英雄的行为是不固定的
使用场景:
需要较高的扩展性时(直接与用户发生交互的程序例如,qq微信)对于不需要扩展的程序而言,使用面向对象反而增加了复杂度
什么是对象:具备某些特征与技能的结合体,是实实在在存在的具体物体
什么是类:类是一个抽象概念,不是实际存在的,是根据一些具备相同特征和技能的对象抽取得到的,比如说人类
类与对象之间的关系:类包含了一系列相同特征和技能的对象, 对象是属于某个类的实例
先有类还是先有对象:在生活中是先有对象再根据对象的特征和技能得到一个类型,在程序中先有类,才能通过类来产生对象,要先确定对象具备什么特征和什么行为才能产生对象
为什么要使用面向对象:很多的程序与用户直接打交道,而用户的需求千变万化,所以对扩展性要求非常高,面向对象编程的本质就是使用不同的对象来完成程序
#在类中描述对象的特征和行为
class Person:
# 用变量来描述特征
name = "李四"
sex = "man"
age = 20
#得到对象,通过调用类,也称之为实例化或创建对象
obj = Person()
print(obj)
#使用对象的属性
print(obj.name)
print(obj.age)
print(obj.sex)
class Student:
number = "007"
name = "盖伦"
sex = "man"
age = 18
# 学生的学校由于每个学生的学校都是相同所以将其放到类中
school = "Tsinghua"
#创建了两个学生对象
stu1 = Student()
stu2 = Student()
#每个对象内存地址都是不同的,在创建对象时,计算机会申请一个新的内存空间,并将对象中的内容存进去
print(stu1) #<__main__.Student object at 0x000001A2B2EC7F28>
print(stu2) #<__main__.Student object at 0x000001A2B2EC7F60>
#由于name的值时声明在类中的,所以每个对象使用的都是同一份
print(id(stu1.name)) #1798298182032
print(id(stu2.name)) #1798298182032
#为对象单独定制属性
#stu1.name = "韩信"
#stu2.name = "陈大炮"
print(stu1.name)
print(stu1.name)
#通过__dict__可以获取一个对象中包含的内容
stu1.age = 30
stu1.name = "韩信"
stu2.name = "陈大炮"
print(stu1.__dict__) #{'age': 30, 'name': '韩信'}
print(stu2.__dict__) #{'name': '陈大炮'}
#获取类中包含的内容
print(Student.__dict__)
class Car:
c_type = "保时捷"
color = "red"
price = 400000
c1 = Car()
c2 = Car()
#当对象中不存在是会到类中去找
print(c1.__dict__) #{}
print(c2.__dict__) #{}
print(c1.c_type) #保时捷
c1.c_type = "法拉利"
print(c1.__dict__) #{'c_type': '法拉利'}
print(c2.__dict__) #{}
print(c1.c_type) #法拉利
print(c2.c_type) #保时捷
总结:
查找顺序为:对象==>类
当创建一个类的时候,会产生名称空间,存储类中名称和值的绑定关系
当创建一个对象的时候,会产生名称空间,存储对象中名称和值的绑定关系
类还有另一个作用就是作为对象的模板,所有属于同一个类的对象,都具备类中的公共内容
即使我们什么都不写 类中也存在一些自带的属性,是从父类得到的
class A:
pass
print(A.__dict__)
class Student:
# 定义一个函数 用于为对象设置属性
def set_attr(obj, name, sex, age):
obj.name = name
obj.sex = sex
obj.age = age
stu1 = Student()
#指定属性
stu1.name = "张无忌"
stu1.sex = "man"
stu1.age = 18
stu2 =Student()
stu2.name = "周芷若"
stu2.sex = "woman"
stu2.age = 78
print(stu2.name) #周芷若
stu3 = Student()
Student.set_attr(stu3,"金毛狮王","man",80)
print(stu3.__dict__) #{'name': '金毛狮王', 'sex': 'man', 'age': 80}
class Person:
#初始化函数名称是固定,该函数会在调用类是时自动执行,self参数必须有,表示要进行初始化的对象,系统会自动传值
def __init__(self,name,age):
print("执行了 __init__")
print(self)
self.name = name
self.age = age
p1 = Person("张三丰",80)
print(p1.__dict__)
p2 = Person("李狗蛋",20)
print(p2.__dict__)
# init 函数用于初始化对象,它会在创建对象时自动执行,并传入调用类时传递的参数,第一个参数表示要初始化的对象本身
# self(第一个)参数不需要手动传递
# 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("张三","man",18)
stu1.sayHI() #hello my name is 张三 my age:18 my sex:man
Student.sayHI(stu1) #hello my name is 张三 my age:18 my sex:man
print(stu1.sayHI) #> 这是一个绑定方法,本质上是Student类中的sayHI函数,现在把这个函数绑定给了地址为0x000001784F889C50的对象
name = "张三"
age = 20
sex = "男"
name1 = "李四"
age1 = 25
sex1 = "男"
name2 = "赵六"
age2 = 30
sex2 = "男"
def show_info(name,age,sex):
print("hello i am %s my age:%s my sex:%s" % (name,age,sex))
show_info(name,sex,age)
show_info(name1,sex1,age1)
show_info(name2,sex2,age2)
# 第一个问题:传递参数,必须手动传递,很有可能传参顺序而发生错误
# 第二个问题:每次处理数据都需要手动传参数
# 第三个问题:当要处理的数据特别的多,就不能再定义为变量了你可以使用列表出来存储要处理的数据
# 但是每次处理都需要先获取数据,在传递给处理数据的函数
# 所以将要处理的数据与处理数据的函数进行绑定
class Student:
school = "beijing"
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
#绑定给类的方法
@classmethod
def print_school(cls):
#输出类里面叫school的属性
print(cls.school)
#这是绑定给对象的方法
def sayHello(self):
print(self.name, "说你好")
#类的绑定方法,对象和类都能调用,并且都会自动传入这个类
Student.print_school() #beijing
stu1 = Student("张三", "woman", 20)
stu1.print_school() #beijing
#对象绑定方法可以使用对象来调用,也可以使用类名来调用
#在对象调用时会自动传入对象自己
#类调用时不会自动传参
练习 :
#有一个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()
什么是非绑定方法:在类中即不绑定给类也不绑定给对象
特点:没有自动传参数的效果,类和对象向都能调用,就是一个普通函数,当你的这个功能不需要访问类的数据也不需要访问对象的数据,就可以作为一个非绑定方法,使用场景较少
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)
练习:
1.创建Student类
2.拥有以下属性: 姓名 性别 年龄 学校 班级
3.拥有以下方法
save(name) 其作用是将这个对象序列化到文件中
get_obj(name) 其作用是根据name从文件中反序列化为得到一个对象
分析save方法和get_obj 应该作为绑定给对象还是绑定给类
import json
class Student:
school = "beijing"
def __init__(self,name,sex,age,classes):
self.name = name
self.age = age
self.sex = sex
self.classes = classes
def save(self):
dic = {"name":self.name,"sex":self.sex,
"age":self.age,"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("张三","woman",20,"py5期")
stu2 = Student("李四","man",20,"py5期")
stu1.save()
stu2.save()
stu = Student.get_obj("张三")
print(stu)
print(stu.name)