目录
面向对象编程——是一种以对象为中心的程序设计思想
面向过程编程——是一种以过程为中心的程序设计思想
问题:把大象装进冰箱,需要几步?
答案:三步
第一步:打开冰箱
第二步:把大象装进去
第三步:关闭冰箱
一、面向过程编程
面向过程是把问题拆分成一个个函数和数据,按照一定的顺序来执行这些方法
上面的答案就是面向过程的编程,遇到问题,一步步解决
二、面向对象编程
面向对象是把问题抽象成一个个对象,给这些对象绑上属性和方法,即以功能而非步骤划分问题
首先面向对象要解决这个问题,需要先建立出抽象模型,比如:打开和关闭冰箱的门,都是属于冰箱的功能;大象走进去,是大象的功能。此时就出现了两个抽象的模型,一个是冰箱,一个是大象。
面向对象的思想,就是要创建冰箱和大象这两个对象,最终完成这个程序。
冰箱对象—开门,大象对象—走进去,冰箱对象—关门
面向对象就是调用对象去解决问题,不管具体的对象如何去解决的,对于我们来说,就是调用了这个对象,而对象去完成这个任务
三、如何学习面向对象的编程
1.学习面向对象编程的思想
2.学习面向对象编程的语法
四、面向过程和面向对象的优缺点
1.面向过程
面向过程的核心是过程,过程就是指解决问题的步骤
优缺点:
✦ 优点:将负责的问题流程化,进而实现简答化
✦ 缺点:扩展性更差(更新,维护,迭代)
总结:完成一些简单的程序时,可以用面向过程去解决。但面对复杂的程序或者任务,而且需要不断的进行迭代和维护时,则优先选择面向对象的编程。
2.面向对象
面向对象的核心是对象,是一个特征和功能的综合体
优缺点:
✦ 优点:可扩展性高
✦ 缺点:编程复杂度相对更高一些。指的是计算机在执行面向对象的程序时的性能表现
3.面向对象的一些名称(术语)
类:类是对象的一个抽象
对象(实例):对象就是由类创建的实例
类和对象的关系就是 模具和铸件的关系
- 类是由对象总结而来的,总结的过程叫抽象
- 对象是由类具体实施出来的,这个过程叫做实例化
五、面向对象编程的基本实现
1.创建类
语法:
class Student():
pass
如果需要实例一个对象,那么需要先抽象一个类
# 面向对象 oop 基本实现
'''
类名的书写规范,建议使用驼峰命名法:
大驼峰:MyCar,XiaoMi
小驼峰:myCar,xiaoMi
一个类有特征和功能两个内容组成:
特征:颜色:白色,品牌:奥迪,排量:2.4 ……
功能:拉货、带美女兜风
特征在编程中就是一个属性,在类中称为 变量
功能在编程中就是一个函数,在类中称为 方法
'''
类中一般属性在前面定义,方法在后面定义
示例:
#定义一个汽车的类
class Cart():
#属性 ==> 特征 ==> 变量
color = '白色'
brand = '奥迪'
pailiang = 2.4
#方法 ==> 功能 ==> 函数
def lahuo(self):
print('小汽车能拉货')
def doufeng(self):
print('小汽车能兜风')
def bamei(self):
print('带妹去嗨……')
如何通过类实例化去使用?
# 如何使用这个类?
# 通过类实例化一个对象
aodiobj = Cart()
print(aodiobj,type(aodiobj))
# 调用对象的方法
aodiobj.doufeng()
# 获取对象的属性
print(aodiobj.brand)
2.对象成员的操作
什么是对象的成员?一个对象通过类实例化之后,那么在类中定义的属性和方法,可以使用实例化的对象进行操作 类中定义的属性也称为 成员属性,类中定义的方法,也称为 成员方法
# 实例化对象
a = Cart()
b = Cart()
print(a)
print(b)
'''
a 和 b都是对象,都是通过Cart这个类实例化出来的,但是他们是两个对象
<__main__.Cart object at 0x000001B3FFA19FD0>
<__main__.Cart object at 0x000001B3FFA19FA0>
'''
# 对象成员的操作
# 在类的外部,使用对象操作成员
# 访问成员属性:先访问a对象自己的color属性,如果没有,就去访问这个对象的类的属性
res = a.color # 通过对象访问类中的属性
a.color = '黑色' # 修改对象的属性
# 此时 b 对象的color属性是什么?
print(b.color) # b对象的属性依然是原来的值
a.name = 'A6' # 给对象添加属性,此时的'name'属性只属于a这个对象
# 此时 b 对象中不会有'name'这个属性
# del a.brand # AttributeError: brand 不能删除
del a.name # 可以删除
'''
删除一个对象的属性时,只能删除当前这个对象自己的属性才可以,
brand这个属性并不属于a对象自己的属性,而是属于Cart这个类的,因此不能删除
name这个属性,是单独给a添加的属性,因此可以删除
'''
# 在类的外部操作对象的方法
# 访问对象的方法:如果这个对象没有自己独立的方法,那么就会访问对象的类的方法
# res = a.lahuo() # 通过对象访问类中的方法
def func():
print('这是一个新的方法')
a.lahuo = func # 把一个函数值赋给成员
a.lahuo() #调用方法
# 添加新的方法
a.func2 = func
# 删除方法
del a.func2 # 可以删除,对象单独添加的方法
del a.lahuo # 可以删除对象改过的方法
del a.bamei # AttributeError: bamei 类的方法,不能删除
3.总结
实际上,在创建对象的时候,不会把类的属性和方法复制一份给对象,而是在对象中引用父类的方法 因此在访问对象的属性时,也会先去找对象自己的属性,如果没有就去找这个对象的类的属性和方法
一个对象由类创建以后,是一个独立的对象,可以引用父类中的属性和方法 如果在对象创建以后,给对象的属性或方法 进行修改或添加,等于给这个对象创建了一个属于自己的属性和方法 所以在删除时,只能删除对象被修改或添加的成员
六、面向对象的三大特征
1.封装:提高程序的安全性
将特征(属性)和功能(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度。
在Python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个"_"
示例:
# 封装
class Student:
def __init__(self,name,age):
self.name = name
self.__age = 20 # 表示变量age在类外部不能被访问
def func(self,name,age):
print(f'{name}的年龄是{age}')
stu1 = Student('张三',30)
print(stu1.name)
# print(stu1.age) # AttributeError: 'Student' object has no attribute 'age'
print(dir(stu1))
print(stu1._Student__age) # 私有属性可以通过_Student__age访问
2.继承:提高代码的复用性
继承和多继承
语法格式:
class 子类类名(父类1,父类2,……)
pass
如果一个类没有继承任何类,则默认继承object
Python支持多继承
定义子类时,必须在其构造函数中调用父类的构造函数
示例:
class Person:
def __init__(self,name,age):
self.name = name
self.age = age # 表示变量age在类外部不能被访问
def func(self):
print(f'{self.name}的年龄是{self.age}')
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score = score
class Teacher(Person):
def __init__(self,name,age,tyear):
super().__init__(name,age)
self.tyear = tyear
stu = Student('lucy',20,80)
teacher = Teacher('jack',35,7) # 实例化
stu.func()
teacher.func() # 调用父类的方法
方法重写
应用场景: 当父类的方法不能满足子类的需求时,可以对方法进行重写(override)
1)覆盖父类方法 子类中定义同名的方法即可,本质来说,调用方法会先在子类中寻找,如果子类没有该方法则到父类中寻找。
2)对父类方法进行扩展 如果子类方法实现中包含了父类方法实现,那么不使用覆盖的方式而是对父类方法进行扩展。 子类中定义同名方法,在需要的位置使用super().父类方法即可
示例:
class Student(Person):
def __init__(self,name,age,score):
super().__init__(name,age)
self.score = score
def func(self): # 方法重写
super().func() # 通过super().func()调用父类中的方法
print(self.score)
stu = Student('lucy',20,80)
stu.func() # 调用重写的方法 ##80
object类
object类是所有类的父类,因此所有类都有object类的属性和方法。
内置函数dir() 可以查看 指定对象所有的属性
object有一个str() 方法,用于返回一个对于“对象的描述”,对应于内置函数str() ,经常用语print() 方法,帮我们查看对象的信息,所以经常会对str() 进行重写
示例:
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print('姓名:{},年龄:{}'.format(self.name,self.age))
def __str__(self):
return '姓名:{},年龄:{}'.format(self.name,self.age)
o = object()
p = Person('jack',20)
print(dir(o))
print(dir(p))
print(p) # 姓名:jack,年龄:20
3.多态:提高程序的课扩展性和可维护性
简单来说,多态就是“具有多种形态”,它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。
多态: 不同的子类对象调用相同的父类方法,产生不同的执行结果。
实现步骤:
- 子类继承父类
- 子类重写父类的同名方法
- 定义一个共同的方法,参数为父类对象,在方法中调用子类和父类同名的方法
示例:
class Animal():
def eat(self):
print('动物会吃')
class Cat(Animal):
def eat(self):
print('猫吃鱼')
class Dog(Animal):
def eat(self):
print('狗吃肉')
class Person(Animal):
def eat(self):
print('人吃五谷杂粮')
def fun(obj):
obj.eat()
#开始调用函数
fun(Cat())
fun(Dog())
fun(Animal())
print('-------------------------')
fun(Person())
多态指同一个方法调用,由于对象不同可能会产生不同的行为。
- 多态是方法的多态,属性没有多态
- 多态的存在有两个必要条件:继承、方法重写
七、特殊属性和方法
1.特殊属性
__ dict __ :获得类对象或实例对象所绑定的所有属性和方法的字典
2.特殊方法
__ len__() | 通过重写len() 方法,让内置函数len()的参数可以是自定义类型 |
---|---|
__ add__() | 通过重写add()方法,可使用自定义对象具有“+”的功能 |
__ new__() | 用于创建对象 |
__ init__() | 对创建的对象进行初始化 |
__ new__()方法
示例:
class Person():
def __new__(cls, *args, **kwargs):
print('__new__被执行调用了,cls的id值是{}'.format(id(cls)))
# __new__被执行调用了,cls的id值是2605846583216 3
obj = super().__new__(cls)
print('创建的对象的id为:{}'.format(id(obj)))
# 创建的对象的id为:2605854928656 4
return obj
def __init__(self,name,age):
print('__inti__方法被调用了,self的id值为:{}'.format(id(self)))
# __inti__方法被调用了,self的id值为:2605854928656 5
self.name = name
self.age = age
print('object这个类对象的id为{}'.format(id(object)))
# object这个类对象的id为140719232921088 1
print('Person这个类对象的id为{}'.format(id(Person)))
# Person这个类对象的id为2605846583216 2
# 创建Person类的实例对象
p1 = Person('张三',20)
# 创建对象的时候,Person被传给了 __new__方法中的cls
# 返回的obj赋值给了__init__方法里的self,self传给p1
print(f'p1这个Person类的实例对象的id为{id(Person)}')
# p1这个Person类的实例对象的id为2605846583216 6
'''
创建对象时,先调用new,返回,再执行inti,cls地址对应类的地址,self地址对应创建的实例的地址
'''