python:面向对象编程
一、面向对象的编程思想
1、面向过程与面向对象
面向过程:自顶向下,逐步细化(各个功能的实现 => 函数的封装)
核心:函数 把一个系统分解为若干个步骤,每个步骤都是一个函数
所谓的面向对象,就是在编程的时候尽可能的去模拟现实世界。
在现实世界中,任何一个操作或业务逻辑的实现都尽可能地需要一个实体完成,实体就是动作的支配者,没有实体,也就没有动作的发生。
面向对象思想:由什么样的主体实现什么样的功能,再把该主体的属性和功能统一进行封装,最后才去实现各个主体的功能
面向对象的核心思想:不仅仅是简单的将功能进行封装(封装成函数),更是对调用该函数的主体进行封装,实现某个主体拥有多个功能,在使用的过程中,先得到对应的主体,再使用主体去实现相应的功能。
2、面向对象的三步骤:
1、 分析哪些步骤是由哪些实体发出的(找对像)
2、 定义这些实体,为其增加相应的属性和功能(找对象的属性和方法)
属性就是实体固有的某些特征特性信息,在面向对象的术语中,属性就是以前的变量
比如:
一个人的属性有:身高、体重、姓名、学历、籍贯、毕业院校等
一个手机的属性有:价格、品牌、操作系统、颜色、尺寸
功能就是这些实体可以完成的动作,在面向对象的术语中,功能就是封装成了函数和方法。
3、 让实体去执行相应的功能或动作(对象执行相应的功能)
3、面向对象的概念:
对象:object,现实业务逻辑中的一个动作实体就对应着面向对象编程的中的一个对象。
- 对象使用属性(property)保存数据
- 对象使用方法(method)管理数据
二、类
1、类的概念:
对象如何产生,又是如何规定对象的属性和方法呢?
答:在python中,采用类(class)来生产对象,用类来规定对象的属性和方法!也就是说,在python中,要想得到对象,必须先有类!
类:类是一个抽象概念(具有相同属性或相似属性和方法的集合)
对象:由类实例化产生的具体事物
一个对象的所有应该具备特征特性信息,都是由其所属的类所决定的,但是每个对象又可以具有不同的特征特性信息。比如学生类,一个对象(实体)姓名为莫航,性别男,会打篮球;另一个对象(实体)姓名为赵薇,性别女,会唱歌。
2、类的定义:
python3中类分为,经典类和新式类
经典类:不由任意内置类型派生出的类,称之为经典类
class 类名:
# 属性 => 变量
# 方法 => 函数
代码
......
新式类:class 类名(object):
在python3中 object 为默认继承的类
class 类名():
# 属性 => 变量
# 方法 => 函数
代码
......
- 其中类名既可以大写也可以小写,遵守一般的标识符的命名规则(以字母,下滑线以及数字组成,且不能以数字开头),一般为了和方法名区分,类名的首字母一般大写!(大驼峰)
- 类在定义构成中,只是描述了这个对象未来应该具有哪些方法和属性,本身并没有调用,只有在实例化对象的时候才真正执行。
3、类的实例化:
类是一个抽象概念,可以同时产生多个对象
类实例化的基本语法:
对象名称 = 类名()
class Person(object):
# 属性
# 方法
# 定义一个方法
def eat(self):
print('I can eat!')
def run(self):
print('I can run!')
# 类的实例化 => 产生一个或多个对象
p1 = Person()
# 产生对象以后,这个对象就拥有了这个类的公共属性与公共方法
# 可以通过 对象名称.公共属性 或 对象名称.公共方法() 实现对自身属性和方法的调用
p1.run() # 调用自身的run()方法
类是一个抽象概念,在定义时,其并不会真正的占用计算机的内存空间。但是对象是一个具体的事物,所以其要占用计算机的内存。
4、类中的self关键字
实例化对象与类在计算机中的内存中关系:
p1 = Person()
print(p1) # 0x000001E47F7DA408
p2 = Person()
print(p2) # 0x000001E47F7DA544
- 变量之间一般都是引用关系
self也是python内置的关键字之一,其指向了类实例对象本身。
在定义类的时候,我们描述的是未来实例化对象所拥有的属性和方法,但是为什么所有的对象方法都有一个参数self,self关键字到底是什么?
class Person(object):
def speak(self):
print(self) # 直接输出self,查看
p1 = Person() # self指向了p1
print(p1) # 0x000001C8ADCB17F0
p1.speak() # 0x000001C8ADCB17F0
p2 = Person() # self指向了p2
print(p2) # 0x000001C8ADCB1730
p2.speak() # 0x000001C8ADCB1730
- 在类定义的对象方法中的self参数,与实例化产生的对象内存地址一致,所以代表两者指向相同的内存空间。所以self关键字就代表实例化对象本身。
- 简单来说,谁实例化了Person类,类中的对象就指向谁,self相当于实例化对象本身。
5、类属性
由于在类内部,self关键字代表对象本身,所以我们在方法的里面可以使用self调用自身的属性和方法。
在类的外部添加与获得属性
可以在类的外部为对象动态添加属性
基本语法:
对象名.属性名 = 属性值
比如:
p1.name = '七落'
p1.age = 18
在类的外部获得属性:
print(p1.name)
print(p1.age)
在类的内部获得类外部为对象添加的属性
在类的内部,我们可以通过对象方法中的self关键字来实现对自身属性和方法的调用
① self指向谁?谁实例化了这个类,self就指向谁(对象)。
② self有何作用?在类的内部,可以通过self.属性或者self.方法()形式来实现对自身属性或方法的调用。
class Person(object):
# 不建议在类内部调用外部动态添加的属性
def print_info(self):
print(f'姓名:{self.name}')
print(f'年龄:{self.age}') # self就相当于实例化对象本身
# 使用Person类实例化对象
p1 = Person()
# 在类的外部动态添加属性
p1.name = '七落'
p1.age = 18
# 通过p1对象,调用print_info()函数
p1.print_info()
扩展:在pychram中从实例化对象开始Debug代码,使用step into
三、魔术方法
1、什么是魔术方法
魔术变量:__name__
,__file__
这些都是魔术变量(拥有特殊功能的变量)
魔术方法:__xxx__()
的函数被称为魔术方法,指具有特殊功能的函数。
魔术方法都有自己的触发条件:
__init__()
当实例化对象时,其会自动被触发(被调用)
__del__()
当手工删除对象或对象被销毁时,其会自动被触发(被调用)
2、__init__()
初始化方法(构造函数)
__init__()
的主要作用就是进行一些初始化工作。(公共属性的初始化或项目的初始化工作)
实际工作场景:
① 在类的定义,用于描述对象所拥有的公共属性
② 用于系统的初始化工作:比如文件操作中的打开文件,数据库操作中的连接数据库等等。
在类中,当实例化对象时,
__init__()
会自动被触发(被调用)
class Person(object):
# 定义一些公共方法
def __init__(self):
self.name = '孙悟空'
self.age = 500
# 通过Person类实例化对象
p1 = Person() # 在实例化对象时,__init__()函数会被调用
print(p1.name) # 孙悟空
print(p1.age) # 500
p2 = Person()
print(p2.name) # 孙悟空
在上述方法中,确实在实例化对象时都初始化了,但是如何赋予不同对象不同的属性值呢?
class Person(object):
# 定义公共属性
def __init__(self, name, age):
# self 代表对象本身(每一个实体)
# self.name 这里的name代表对象的属性,那么可以通过传参实现赋予不同对象不同的属性值
self.name = name # 对象属性 = 参数
self.age = age
# 定义公共方法
def speak(self):
# self可以在类内部调用自身的属性或者方法
print(f'姓名:{self.name},年龄:{self.age}')
# 通过Person类实例化对象p1
p1 = Person('七落', 20) # 在实例化对象时,__init__()就被调用
# 调用一下speak函数
p1.speak() # 姓名:七落,年龄:20
# 实例化 P2
p2 = Person('莫航', 19)
p2.speak() # 姓名:莫航,年龄:19
3、__str__()魔术方法
当使用print输出对象的时候,默认打开对象的内存地址。如果类中定义了__str__()
方法,就会打印从这个方法中return的数据。(其中,__str__()
方法返回值为字符串类型)
掌握一个魔术方法有两个地方:什么情况下会被触发?在实际工作中__str__()
有什么作用?
- 当我们使用print() 函数直接打印对象时,
__str__()
会自动被触发 - 当我们需要打印某个对象的信息时,一般可以定义
__str__()
魔术方法
# 定义一个汽车类
class Car(object):
# 初始化,定义公共属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
# 定义__str__()魔术方法
def __str__(self):
return f'汽车的品牌:{self.brand},型号:{self.model},颜色:{self.color}' # 返回值必须为字符串类型
bmw = Car('宝马', 320, '黑色')
print(bmw) # 没有定义__str__()方法,返回值为
# <__main__.Car object at 0x0000021197F21A00>
print(bmw) # 定义__str__()方法,返回值为
# 汽车的品牌:宝马,型号:320,颜色:黑色
4、__del__()
删除方法(析构方法)
__init__()
与__del__()
是一对的:
__init__()
:构造函数,用于项目的初始化
__del__()
:析构函数,项目的清理或项目的收尾工作
主要作用:用于清除对象或实现项目清理工作,如:关闭文件,关闭数据库的连接
触发条件:当对象被删除时会自动被触发 ① 手动 del 对象 ② 当程序执行结束,内存开始清理对象时
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
# 定义一个析构函数
def __del__(self):
print('当 del 对象时,析构函数会自动被触发!')
p1 = Person('小白', 19)
- 当程序执行结束,内存清理对象时候,
__del__()
会自动被触发
del p1
- 手工清理对象时,
__del__()
也会自动触发
四、综合案例
1、打印学生学业成绩水平
class Student(object):
# 定义Student类的公共属性
def __init__(self, name, score):
self.name = name
self.score = score
# 定义Student类的公共方法
def print_score(self):
if self.score >= 90:
print(f'姓名:{self.name},成绩:{self.score},优秀')
elif self.score >= 80:
print(f'姓名:{self.name},成绩:{self.score},良好')
elif self.score >= 70:
print(f'姓名:{self.name},成绩:{self.score},中等')
elif self.score >= 60:
print(f'姓名:{self.name},成绩:{self.score},合格')
else:
print(f'姓名:{self.name},成绩:{self.score},不合格')
# 实例化对象
student1 = Student('莫航', 75)
# 调用print_score方法,显示成绩水平
student1.print_score()
- 在实际工作中,为了保证数据的安全性,一般不建议在类的外部调用自身的属性,如果想调用自身的属性和方法都是通过对应的方法实现的!
2、小明减肥案例
class Person(object):
def __init__(self, name, weight):
self.name = name
self.weight = weight
def run(self):
# 每次调用run,都可以减少自身的体重
self.weight -= 0.1
return self.weight
def eat(self):
# 每次调用eat()都增加自身的体重
self.weight += 0.2
return self.weight
# 定义一个魔术方法,直接打印实例化对象就输出这个信息
def __str__(self):
return f'姓名:{self.name},当前体重:{self.weight:.2f}'
p1 = Person('小明', 75)
p1.run()
print(p1) # 姓名:小明,当前体重:74.90
p1.run()
p1.run()
print(p1) # 姓名:小明,当前体重:74.70
3、搬家具案例
# 定义一个家具类
class Furniture(object):
# 定义公共属性(家具类型以及占用面积)
def __init__(self, model, area):
self.__model = model # 私有属性
self.__area = area
# 定义一个接口,方便在类的外部获取 对象的家具类型
def getmodel(self):
return self.__model
# 定义接口,提供在类的外部获取家具的面积
def getarea(self):
return self.__area
# 输入家具信息时,显示家具的类型和家具占用的面积
def __str__(self):
return f'家具的类型:{self.__model},占用的面积:{self.__area}平方米'
# 定义一个房子类
class House(object):
# 定义房子的公共属性(地址和面积)
def __init__(self, address, area):
self.address = address
self.area = area # 用来获取添加家具之后房子剩余的可用面积
self.area1 = area # 用来获取房子的总面积
self.item = [] # 定义一个列表,用来存储家具(存储的是一个个家具对象)
# 定义一个添加工具的功能
def add_furniture(self, furniture): # 传入的参数为家具的实例化对象
needArea = furniture.getarea() # 通过getarea方法获取家具的面积
if self.area >= needArea:
self.item.append(furniture.getmodel()) # 通过getmodel方法获取家具的名字
self.area -= needArea # 房子的可用面积
print('家具添加成功!')
else:
print('面积不足,家具添加失败!')
# 输出房子信息时,可以显示房子的地址,占地面积,剩余面积以及其中的家具
def __str__(self):
if len(self.item) > 0:
msg = ''
for i in self.item:
msg = msg + i + '、'
return f'房子的地址:{self.address},占地面积:{self.area1}平方米, 剩余面积:{self.area}平方米!' + '其中的家具有:' + msg.strip('、') # strip()字符串的一个方法,默认去掉字符串两边的空格(包括换行\n,\t等)
bed = Furniture('席梦思床', 4)
print(bed)
sofa = Furniture('沙发', 6)
print(sofa)
my_house = House('广州市天河区', 100)
my_house.add_furniture(bed) # 添加床
my_house.add_furniture(sofa) # 添加沙发
print(my_house)
标签:__,p1,python,self,对象,面向对象编程,print,属性
From: https://www.cnblogs.com/luoluoange/p/17717492.html