17 面向对象 - oop
面向对象编程--Object Oriented Programming,oop,一种以对象为中心的程序设计思想
面向过程编程--Procedure Oriented Programming,pop,一种以过程为中心的程序设计思想
如何理解面向对象和面向过程:
问题:把大象装进冰箱,分几步?
- 面向过程:
遇到问题,分析解决问题的步骤,然后一步步去实现
三步:打开,装进,关上。
- 面向对象:
通过分析问题中需要的抽象模型,根据需要的功能分别去创建模型对象,最终由模型对象来完成程序
调用对象去解决问题
需要先建立出抽象模型,比如,打开冰箱和关闭冰箱门,都属于一个冰箱的功能,大象走进去,是大象的功能。此时出现了两个抽象模型,冰箱,大象。
冰箱具有打开和关闭的功能,大象具有走路的能力。
分析到这里,就是面向对象的思想,具体完成时,去创建冰箱和大象两个对象,最终完成这个程序: 冰箱对象-开门,大象对象-走冰箱,冰箱对象-关门
想吃清蒸鱼,怎么办?
面向过程:
1,买鱼买料 ; 2,杀鱼清理腌制 ; 3, 放锅烧水,放鱼开蒸 ; 4,准备浇汁 ; 5,十分钟后取鱼,浇汁
面向对象:
需要一个对象:大厨 , 告诉大厨我想吃清蒸鱼
面向对象就是调用对象解决问题,具体对象如何解决,大厨这个对象也是一步一步去完成,但对于我来说就是调用对象,对象去完成这个过程
最终面向对象,是有面向过程的体现
17.0 面向对象的总结和 类与对象
一、面向过程
面向过程的核心是过程,过程就是指解决问题的步骤
优缺点:
- 优点:将复杂的问题流程化,进而实现简答化
- 缺点:扩展性差(更新、维护、迭代)
总结:完成一些简单的程序时,可以使用面向过程去解决,但如果有复杂的程序或任务,且需要不断地进行迭代和维护,优先选择面向对象的编程思想
二、面向对象
面向对象的核心是对象,是一个特征和功能的综合体
优缺点:
- 优点:可扩展性高
- 缺点:编程复杂度相对面向过程高一些。指的是计算机在执行面向对象的程序时的性能表现
三、面向对象中的一些名词(术语)
类:类是对象的一个抽象的概念
对象(实例):由类创建的实例
类和对象的关系就是 模具与铸件的关系
1.类是由对象总结而来的,总结的过程叫做抽象
2.对象是由类具体实施出来的,这个过程叫做实例化
水果是一个对象还是一个类,汽车?
属性 方法
17.1 面向对象的基本实现
创建对象前,需要构建一个类,由类实例化对象
class 关键字定义一个类
class 类名():
pass
类名的书写规范,建议使用驼峰命名法:
大驼峰:MyCar XiaoMi
小驼峰:myCar xiaoMi
一个类有特征和功能两个内容组成
特征在编程中就是一个变量,在类中称为 属性
功能在编程中就是一个函数,在类中称为 方法
类中属性一般定义在前面,方法定义在后面
class Car():
# 属性 == 特征 = 变量
brand = 'linkhen'
color = 'white'
quantity = 'high'
price = 100000
# 方法 == 功能 == 函数
def play(self):
print('play around with girls')
def business(self):
print('do some business')
def utility(self):
print('driving instead of walking long distance')
# 将类实例化为一个对象
owner = Car()
# 调用对象的方法
owner.play()
# 调用属性
print(Car.brand)
print(owner.brand)
17.2 对象成员的操作
一个对象通过类实例化后,在类中定义的属性和方法,可以使用实例化的对象进行操作
类中定义的属性,也称为成员属性;方法也称为成员方法
a = Car()
b = Car()
print(a) # <__main__.Car object at 0x00000000023EC208>
print(b) # <__main__.Car object at 0x00000000023EC248>
'''
一个类可以实例化多个对象
a和b变量都是对象,由同一个类实例化出来,是两个对象
'''
17.2.1. 在类的外部,使用对象操作属性
1.调用对象属性
访问成员属性,先访问a对象自己的属性,没有则去访问对象的类的属性
a = Car()
b = Car()
res = a.price
print(res) # 30万
res = a.business() # do some business
print(res) # None
2.修改对象属性
实际上相当于给这个对象创建了一个对象自己的属性
print(b.color) # white
b.color = 'black'
print(b.color) # black
3.添加对象属性
给当前对象添加了属于该对象的属性
a.name = 'A6'
print(a.name)
4.删除对象属性
只能删除属于当前对象的属性
# del a.brand # 删除不了
del a.name # 可以删除
print(a.name)
删除一个对象的属性时,只能删除当前对象独有的属性,无法删除属于类的属性
17.2.2. 在类的外部,操作对象的方法
1.访问对象的方法,若该对象没有自己独立的方法,那么会访问对象的类的方法
res = a.play() # play around with girls
2.修改对象的方法
a.play = print('play around world') # 可以直接运行出来
# 这是属性不是方法
def one():
print('run the fee')
a.play = one
a.play()
3.添加新的方法
def func():
print('short the time')
a.usage = func
a.usage()
4.删除方法
del a.usage
总结:
一个类定义类成员属性和成员方法,通过这个类实例化的对象, 在创建对象时,并不会把类中的属性和方法复制一份给对象,而是让对象引用父类的属性方法
访问对象属性时,会先找对象自己的属性,若无,则找父类的属性
一个对象由类创建后,是一个独立的对象,引用父类的属性和方法
当修改或添加对象的属性或方法时,相当于为该对象创建了一个独立的属性和方法
因此 删除时 只能删除 独立的该对象的属性方法
17.3 类成员的操作 -了解
17.3.1 在类的外部,可以直接通过类对成员进行操作
一、类成员属性的操作
print(Car.brand)
# 修改属性
Car.brand = 'Infinite'
print(Car.brand)
# 给类添加成员属性
Car.number = 'UC S3T09'
print(Car.number)
# 删除属性
del Car.number
del Car.brand
二、类成员方法的操作
class Car():
brand = 'linkhen'
def play(self):
print(f'{self} play around with girls')
def business(self):
print('do some business')
a = Car()
b = Car()
def func(self):
print('so confused')
# 访问类的方法
Car.play('howard')
Car.business(0)
# 修改类的方法
Car.play = func
Car.play(1)
# 添加类的方法
Car.one = func
Car.one('i')
a.one()
# 删除类的方法
del Car.one
a.one()
17.4 类与对象的基本操作总结
- 一个类可以实例化多个对象,每个对象在内存中都独立存在
- 当通过类实例化对象时,并不会把类中的成员复制一份给对象,而是给了一个引用
- 访问对象成员时,若对象自己没有这个成员,对象会从实例化它的类中查找
- 对象成员的添加和修改,都只会影响当前对象自己,不会影响类和其他对象
- 删除对象的成员时,必须是该对象自己具备的成员才可以,无法删除类中的成员
- 对类的成员进行操作,会影响引用该类的对象的成员,包括操作前创建的对象
17.5 类的 self 详解
17.5.1 成员方法中的self
- self在方法中只是一个形参,并不是关键字
- self在方法中代表的是 当前这个对象自己
- self在方法中代表对象可以去操作成员,可以使用self在类的内部访问成员
- self代表调用这个方法的对象,谁调用,self就代表谁
- self可以在类的内部代替对象进行各种操作
class Person():
name = 'zhang'
age = 130
sex = 'human'
def dance(self):
print(f'{self.name} dance when have feelings')
def innovate(self):
printe('innovate things')
def func(self):
# 在类的内部,访问和操作成员
print(self) # 1. <__main__.Person object at 0x000000000214AF88>
print(self.name) # 访问对象的属性
self.name = 'lisi' # 修改对象的属性
self.ai = 'self' # 添加对象属性
print(self.name)
print(self.ai)
self.dance() # 调用对象的方法
# 只要是对象能做的事,self都可以代替对象完成
zs = Person()
print(zs) # <__main__.Person object at 0x000000000214AF88>
zs.func() # 1. <__main__.Person object at 0x000000000214AF88>
'''
self 代表调用这个方法的对象
self 可以在类的内部代替对象进行各种操作
谁调用了这个方法,就代表谁
'''
# 在类的内部
# zs.func()
17.5.2 绑定类方法 和 非绑定类方法
绑定类方法:不含self或者不能接受对象作为参数的方法
非绑定类方法:含有self或者key接受对象作为参数的方法
绑定类方法:只能使用类进行访问
非绑定类方法:可以使用对象和类去访问
- 在类中定义的方法不含self或者其他代替的形参,该方法就不能用对象去调用
- 不含self形参的方法,只能用类调用
class Person():
name = 'zheng'
def func():
print('no')
zs = Person()
zs.func() # TypeError: func() takes 0 positional arguments but 1 was given
Person.func()
17.6 初始化方法
魔术方法 初始化方法
魔术方法:
和普通方法一样,都是类中定义的成员方法
不需要手动调用,在某种情况下,自动触发(自动执行)
多数的魔术方法,前后都有两个连续的下划线
魔术方法,不是自己定义的,而是系统定义好的,我们来使用
__init__初始化方法
触发机制:通过类实例化对象化,自动触发的一个方法
作用:可以在对象实例化后,完成对象的初始化(属性的赋值,方法的调用)
应用场景:文件的打开,数据的获取,干活前的一些准备工作。。。
注意事项:
class Person():
name = None
age = None
sex = None
# 初始化方法
def __init__(self,n,a,s):
print('this is an init method')
# 1. 完成对象属性的初始化
self.name = n
self.age = a
self.sex = s
# 2. 调用方法
self.dance()
def dance(self):
print(f'{self.name} can dance when have feelings')
# 实例化对象
# zs = Person() # this is an init method
# zs = Person('zhang',77,'male') # 1. this is an init method
zs = Person('oscar',44,'male')
# 2. this is an init method
# oscar can dance when have feelings
17.7 析构方法
__del__析构方法:
触发机制:当前类实例化的对象被销毁时,自动触发
作用:可在析构方法中完成一些特殊任务,如:在初始化方法中打开的文件
注意:是对象被销毁时出发了这个方法,而不是这个方法销毁了对象
对象会在哪些情况下被销毁?
1. 当程序执行完毕,内存中所有的资源都会被销毁释放
2. 使用 del 删除
3. 对象不再被引用时,会自动销毁
import time
class WriteLog():
fileurl = './'
filename = '2021.10.1.txt'
# 初始化,打开文件
def __init__(self):
# fileurl = './'
# filename = self.strftime('%Y-%m-%d')+'.log'
self.fileobj = open(self.fileurl + self.filename,'a+',encoding='utf-8')
# 写日志的方法
def log(self,s):
print(f'把日志:{s},写入文件中')
# 析构方法
def __del__(self):
print('析构方法触发了')
# 对象被销毁时,关闭在初始化方法中打开的文件对象
self.fileobj.close() # 注意!注意!!!!
# 实例化对象
re = WriteLog()
re.log('today is windy day')
print('....') # 执行这个之后才会触发析构
# del re # 先执行del,后print下面的
# 对象没有被引用
WriteLog()
print('...1')
class Car():
brand = None # 注意 !!方法中要有对应的赋值才可以运行
# brand = '' 同理
def __init__(self,b):
self.brand = b
print(f'{self.brand} has produced')
def __del__(self):
print(f'{self.brand} has destroyed')
a = Car('Baoma')
b = Car('Aodi')
c = Car('Benz')
# 1. 执行结果?
'''
Baoma has produced
Aodi has produced
Benz has produced
Baoma has destroyed
Aodi has destroyed
Benz has destroyed
'''
Car('Baoma')
Car('Aodi')
Car('Benz')
# 2. 执行结果?
'''
Baoma has produced
Baoma has destroyed
Aodi has produced
Aodi has destroyed
Benz has produced
Benz has destroyed
baoma创建后没有被引用,因此销毁
'''
17.8 日志类的封装
'''
日志类:
class Mylog
功能:
能够随时写入一个日志信息
分析:
位置? 默认在当前目录
名称? 当前日期 2021-10-1.log
格式? [2021-10-1 12:00:00 错误信息。。。]
属性:成员属性的作用就是存储信息,供成员方法来使用
fileurl 日志文件的地址
filename 日志文件的名称
fileobj 打开的文件对象
方法:具体完成的一个功能的过程
__init__() 初始化方法,完成对象的初始化,并打开文件
wlog() 负责接收提供的日志信息,并写入到日志文件中
__del__() 析构方法,在对象被销毁时,关闭打开的文件
'''
import time
class Mylog():
fileurl = './'
filename = time.strftime('%Y-%m-%d')+'.log'
fileobj = None
def __init__(self):
self.fileobj = open(self.fileurl+self.filename,'a+',encoding='utf-8')
def wlog(self,s):
date = time.strftime('%Y-%m-%d %H:%M:%S ')
msg = date + s
self.fileobj.write(msg+'\n')
print(f'{s} is already recorded')
def __del__(self):
self.fileobj.close()
print(f'{self.filename} is closed')
# 实例化对象
s = Mylog()
# 调用方法,写日志
s.wlog('nice nice day')