一、面向对象
1.概念
1.1面向对象的设计思想
面向对象是基于万物皆对象这个哲学观点。在Python中,一切皆对象
举例说明:
案例一:我想要吃大盘鸡
面向过程 面向对象
1.自己去买菜 1.委托一个会砍价的人帮忙去买菜
2.自己择菜 2.委托一个临时工帮忙择菜
3.自己做菜 3.委托一个厨师帮忙做菜
4.自己开始吃 4.自己开始吃
案例二:小明是一个电脑小白,想要配一台电脑,买完零件后需要运到家里,组装完成后打开电脑玩游戏
面向过程 面向对象
1.小明补充电脑知识 1.委托一个懂电脑的朋友(老王)去帮忙买零件
2.小明去买零件 2.委托一个能跑腿的人去买零件
3.小明把零件带回家里 3.委托一个会组装电脑的人帮小明组装电脑
4.小明组装电脑 4.小明自己打开电脑,开始玩游戏
5.小明开机玩电脑
案例三:一辆白色的奥迪Q5在京藏高速上行驶
这里的奥迪Q5就是一个对象,京藏高速也是一个对象
1.2面向过程和面向对象的区别【面试题】
面向过程
在生活案例中:
一种看待问题的思维方式,在思考问题的时候,着眼于问题是怎样一步一步解决的,然后亲力亲为的去解决问题
在程序中:
代码从上而下顺序执行
各模块之间的关系尽可能简单,在功能上相对独立
每一模块内部均是由顺序、选择和循环三种基本结构组成
其模块化实现的具体方法是使用子程序
程序流程在写程序时就已决定
面向对象
在生活案例中:
也是一种看待问题的思维方式,着眼于找到【一个具有特殊功能的具体个体,然后委托这个个体去做某件事情】,我们把这个个体就叫做对象,一切皆对象
是一种更符合人类思考习惯的思想【懒人思想】,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者
在程序中:
把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象
1》对同类对象抽象出其共性,形成类
2》类中的大多数数据,只能用本类的方法进行处理
3》类通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信
4》程序流程由用户在使用中决定
5》使用面向对象进行开发,先要去找具有所需功能的对象,如果该对象不存在,那么创建一个具有该功能的对象
注意:面向对象只是一种思想,并不是一门编程语言,也不会绑定编程语言
面向过程和面向对象的优缺点【面试题】
面向过程:
优点:性能比面向对象高,开销比较大,比较消耗资源,比如单片机、嵌入式开发等一般采用面向过程开发,因为性能是最重要的因素
缺点:没有面向对象易维护,易复用,易扩展
面向对象:
优点:易维护,易复用,易扩展,由于面向对象有封装,继承,多态的特性,可以设计出低耦合的系统,使得系统更加灵活,更加易于维护
缺点:性能比面向过程低
Python是一门面向的语言,面向对象语言的特点:封装,继承和多态
狗吃屎:面向对象
吃狗屎:面向过程
2.类和对象
2.1概念
类:一个具有特殊功能的实体的集合【群体】,是抽象的
对象:在一个类中,一个具有特殊功能的实体,能够帮忙解决特定的问题【对象也被称为实例】,是具体的
两者之间的关系:类用于描述某一类对象的共同特征,而对象则是类的具体存在(包含关系)
问题:先有对象还是先有类?
【不好说,但是,一般在程序中,都是先定义类,然后通过类创建对象】
举例:
类 对象
人 张三、李四、王麻子、杨阳。。。
SuperHero 蝙蝠侠、蜘蛛侠、美国队长。。。
快递 顺丰、圆通、申通、韵达。。。
帮助理解:类也是一种数据类型,只不过是自定义的【系统类ValueError,NameError….】,跟所学过int,str,bool等类似。用类实例化对象相当于定义一个类的变量
num = 10
print(type(num)) # <class 'int'>
# 定义类Person
p = Person()
print(type(p)) # <class '__main__.person'>
2.2类的定义和对象的创建
格式:
class 类名():
类体
说明:
a.Python中使用class关键字定义类
b.类名只要是一个合法的标识符即可,但是要求:遵循大驼峰命名法 ,如:KeyError,ValueError,NameError,IndexError…….
c.尽量使用单个或多个有意义的单词连接而成
d.通过缩进来体现类体的存在
e.类体一般包含两部分内容:对类的特征描述和行为描述
# 一、类的定义
print("start~~~~~")
class MyClass1():
print("1111")
class MyClass2():
print("2222")
class MyClass3():
print("3333")
class MyClass4():
print("4444")
print("over~~~~~")
"""
注意:
a.在同一个py文件中,可以同时定义多个类,但是,在复杂的需求中,一般是一个模块定义一个类
b.class xxx(): 表示类的声明,类名尽量遵循大驼峰命名法,()可以省略,但是在Python3.x中,建议加上
c.缩进的内容被称为类体【类的实现】,在其中会定义类的成员【类的特征描述和行为描述】,
一个类一旦定义完成之后,其中的的成员会被加载
"""
# 二、对象的创建/类的实例化/对象的实例化
# 语法:类名(....)
num = 10
print(type(num)) # <class 'int'>
print(MyClass1) # <class '__main__.MyClass1'>
mc1 = MyClass1()
print(type(mc1)) # <class '__main__.MyClass1'>
print(id(mc1))
print(mc1)
mc2 = MyClass1()
print(mc2)
mc3 = MyClass1()
print(mc3)
"""
注意:
a.假设定义类MyClass,直接使用MyClass表示类名,同时表示一种数据类型,使用MyClass()表示创建对象
b.m = MyClass(),m本质是一个变量,该变量的类型是MyClass类型,变量m中存储的是创建出来的对象的地址
c.MyClass()该代码执行一次,则表示创建一个新的对象
d.一般情况下,一个类可以创建无数个对象
"""
2.3类的设计
只需要关心3样东西
事物名称(类名):人类(Person)
特征:身高(height)、年龄(age)—————》名词———》变量
行为:跑(run)、打架(fight)———————》动词————》函数
初期学习,通过提炼动名词进行类的提取
3.类中的成员
3.1定义和访问
# 一、类中成员的定义
# 1.定义类
class Person():
# 类体:特征和行为
# 2.特征:变量
# 3.行为:函数
"""
关于self:
a.self,自己,自身,表示当前对象
b.哪个对象调用函数,其中的self则表示哪个对象
c.self作为形参中一部分,不能省略,同时调用函数的时候,不需要手动给self传参
d.当调用函数的时候,系统会自动把当前对象传参给self
e.self其实并不是一个关键字,但是常用self,表示当前对象
"""
def eat(self,sth):
print(f"eating {sth}")
def run(self):
print('running',id(self))
# 二、访问类中成员
# 1.调用类中的函数,语法:对象.函数(实参)
per1 = Person()
print(f"per1的地址:{id(per1)}")
per1.run()
per1.eat("apple")
per2 = Person()
print(f"per2的地址:{id(per2)}")
per2.run()
per2.eat("food")
# 2.类的特征【变量/属性】
per = Person()
per.name = "张三"
per.age = 18
print(per.name,per.age)
"""
注意:
a.类中的成员在类的里面不能直接访问,需要通过对象或类访问
b.类的行为【函数】可以直接定义在类的内部,类的特征【变量】可以直接绑定
"""
3.2动态绑定属性和限制绑定
# 1.对象属性的动态绑定
class Person():
def show(self):
print(f"姓名:{self.name},爱好:{self.hobby},成绩:{self.score}")
# 语法:对象.属性 = 值,属性名自定义
per = Person()
per.name = "张三"
per.age = 18
per.hobby = "唱歌"
per.score = 100
print(per.name,per.age)
per.show() # self--->per
# 注意1:给一个对象动态绑定属性,和其他对象没有任何关系
# per2 = Person()
# print(per2.name)
# 注意2:给多个对象绑定了重名的属性,一个对象的属性值发生改变,对其他对象的属性没有影响
per2 = Person()
per2.name = "李四"
per.name = "tom"
print(per2.name)
print("*" * 50)
# 2.限制对象属性的动态绑定
class Person():
# __slots__ = ('字段1','字段2'.....),在元组中的字段表示允许动态绑定的字段
# 注意:如果需要绑定的属性只有一个,则__slots__ = ('字段',)
__slots__ = ("name",'hobby','score')
def show(self):
print(f"姓名:{self.name},爱好:{self.hobby},成绩:{self.score}")
per = Person()
per.name = "张三"
per.hobby = "唱歌"
per.score = 100
# per.age = 18 # AttributeError: 'Person' object has no attribute 'age'
per.show()
4.构造函数
先创建对象,然后使用直接赋值【动态绑定属性】方式给对象绑定属性,可以使用,但是代码比较繁杂,一般情况下,很多类倾向于将对象创建为有初始状态的,在类中可以定义一个函数,名称为__init__,该特殊的函数被称为构造函数,主要用于创建对象并将对象的数据做出初始化
强调:构造函数包括__new__和__init__
构造函数,也被称为构造器,指的是当创建对象的时候,被自动调用的函数
语法:
def __init__(self):
函数体
# 1.未使用构造函数之前
class Person1():
__slots__ = ('name','age')
p1 = Person1()
p1.name = 'aaa'
p1.age = 10
p2 = Person1()
p2.name = 'bbb'
p2.age = 15
p3 = Person1()
p3.name = 'ccc'
p3.age = 17
print("*" * 50)
# 2.构造函数的工作原理
"""
注意:
a.如果类中未定义构造函数,当创建对象的时候,系统会自动调用构造函数
b.构造函数包含:__new__()和__init__()
c.p = Person().实际代码在执行的时候,p获取的是__new__的返回值
d.如果将__new__显式的定义出来,则__new__的返回值必须是一个对象:super().__new__(cls)
e.先调用__new__,然后调用__init__
f.工作原理:先通过__new__创建一个对象,然后将该对象传参给__init__中的self,进行初始化
g.__new__()和__init__()是在创建对象的过程中自动调用的,无需手动调用
"""
class Person2():
__slots__ = ('name', 'age')
# a.__new__:表示从无到有的过程,表示创建对象
def __new__(cls, *args, **kwargs):
print("new~~~~~")
# super().__new__(cls)表示创建一个对象
return super().__new__(cls)
# b.__init__:表示初始化,初始化由__new__创建的对象
def __init__(self,name,age):
print("init~~~~~~")
# 动态绑定属性
self.name = name
self.age = age
p21 = Person2('aaa',10)
print(p21)
print(p21.name,p21.age)
p22 = Person2('bbb',15)
print(p22)
print(p22.name,p22.age)
p23 = Person2('ccc',18)
print(p23)
# 3.实际使用
# 注意:在实际使用的时候,只需要定义构造函数中的__init__,当创建对象的时候,需要和__init__的参数匹配
class Person3():
__slots__ = ('name', 'age')
def __init__(self,name,age):
self.name = name
self.age = age
p31 = Person3('aaa',10)
print(p31)
print(p31.name,p31.age)
5.综合练习
# 需求:开学了,王老师让学生【小明,小花,小丽】做自我介绍
# 介绍姓名,年龄,爱好,来一段才艺展示
"""
分析:
老师类:
特征:姓名
行为:让 .... 做自我介绍
学生类:
特征:姓名,年龄,爱好
行为:做自我介绍,来一段才艺展示
"""
class Teacher():
__slots__ = ("name",)
def __init__(self,name):
self.name = name
# stu表示的是学生对象,并不是一个字符串
def let_stu_introduce(self,stu):
# self表示王老师的对象,stu表示的xiaoming的对象
print(self.name + "让" + stu.name + "做自我介绍")
# 让学生执行自己的行为
stu.introduce()
if stu.name == "小花":
stu.sing()
elif stu.name == "小丽":
stu.dance()
elif stu.name == "小明":
stu.lie()
class Student():
__slots__ = ("name","age","hobby")
def __init__(self,name,age,hobby="学习"):
self.name = name
self.age = age
self.hobby = hobby
def introduce(self):
print(f"大家好,我是{self.name},今年{self.age},爱好:{self.hobby}")
def sing(self): # 小花
print("娘子~~~~啊哈")
def dance(self): # 小丽
print("广场舞")
def lie(self): # 吹牛逼
print("我家就有几千头羊,几千头牛~~~~~")
# 创建老师的对象
wang = Teacher("王老师")
# 创建学生的对象
xiaoming = Student("小明",8,"吹牛逼")
xiaohua = Student("小花",5,"唱歌")
xiaoli = Student(name="小丽",age=10,hobby="跳舞")
# 让老师执行自己的行为
wang.let_stu_introduce(xiaoming)
wang.let_stu_introduce(xiaohua)
wang.let_stu_introduce(xiaoli)