python 基础系列(四) — Python中的面向对象

python基础系列索引
python 基础系列(一) — Python介绍
python 基础系列(二) — Python基本语法
python 基础系列(三) — Python中的变量进阶
python 基础系列(四) — Python中的面向对象
python 基础系列(五) — Python中的继承
python 基础系列(六) — Python的异常及其处理
python 基础系列(七) — Python中的模块
python 基础系列(八) — Python中的文件操作
python 基础系列(九) — Python中的vi – 终端中的编辑器
python 基础系列(十) — Windows CMD命令大全
python 基础系列(十一) — 使用PyCharm远程调试树莓派python代码 — Windows CMD命令大全
如果你对python感兴趣,不妨看一下我的其他文章
-
面向过程
- 注重步骤和过程,不注重职责和分工
- 如果需求复杂代码会变的非常复杂
- 开发复杂项目,没有固定套路,开发难度很大
-
面向对象
类和对象
类和对象是面向对象编程的两个核心概念
- 类是对一群具有相同特征事物的统称,是抽象的 不能直接使用
- 特征 被称为 属性
- 行为 被称为 方法
类
python中的类名
- 使用大驼峰命名法 如
CapWords
- 单词与单词之间不使用下划线
对象
-
1.dir查看内置函数
-
在python中 对象几乎是无处不在的,我们之前学习的 变量、数据、函数 都是对象
python中验证对象有两种方式
-
1.在 标识符/数据 后输入一个
.
按下TAB
键,ipython
会提示该对象能够调用的 方法列表 -
2.使用内置函数
dir
出入标识符/数据 , 可以查看对象内的所有属性及方法
属性:
序号 | 方法名 | 类型 | 作用 |
---|---|---|---|
01 | new | 方法 | 创建对象时,会自动调用 |
02 | init | 方法 | 对象被初始化时,会自动调用 |
03 | del | 方法 | 对象被从内存中销毁前,会被自动调用 |
04 | str | 方法 | 返回对象的描述信息,print函数输出使用 |
以后的学习可以使用dir() 函数,查看对象的方法
1.python中类的定义
python 中的类符合以下的语法格式
Class 类名:
def 方法1(self,参数列表):
pass
def 方法2(self,参数列表):
pass
- 方法 的定义格式和之前的函数 几乎一样
- 区别在于第一个参数必须是
self
注意: 类名 的命名规则 要符合 大驼峰命名规则
创建对象
-
当一个类定义完成之后,要使用这个类来创建对象,语法如下:
对象变量 = 类名()
示例代码
class Cat:
def eat(self):
print("小猫爱吃鱼")
def drink(self):
print("小猫爱喝水")
# 创建小猫对象
cat = Cat()
cat.eat()
cat.drink()
运行结果
小猫爱吃鱼
小猫爱喝水
方法中的 self 参数
可以使用 对象.变量名 = 变量值得方式来增加变量并赋值
- 注意:这种方式虽然简单但是并不推荐
示例代码:
class Cat:
def eat(self):
print("小猫爱吃鱼")
def drink(self):
print("小猫爱喝水")
# 创建小猫对象
cat = Cat()
cat.name="猫主子"
cat.eat()
cat.drink()
print(cat.name)
执行结果
小猫爱吃鱼
小猫爱喝水
猫主子
使用self在方法内部输出每一只猫名字
哪一个对象调用方法,方法内部的 self
就是 哪一个对象的引用
- 在类封装的方法内部,
self
就表示 当前调用方法的对象自己 - 调用方法时,程序员不需要传递
self
参数 - 在方法内部
- 可以通过
self
,访问对象的属性 - 也可以通过
self
, 调用其他的对象方法
- 可以通过
于是代码如下
class Cat:
def eat(self):
print("%s 爱吃鱼" % self.name)
def drink(self):
print("%s 爱喝水" % self.name)
# 创建小猫对象
cat = Cat()
cat.name = "猫主子"
cat.eat()
cat.drink()
print(cat.name)
# 创建小猫对象
Tom = Cat()
Tom.name = "Tom"
Tom.eat()
Tom.drink()
print(cat.name)
示例代码
猫主子 爱吃鱼
猫主子 爱喝水
猫主子
Tom 爱吃鱼
Tom 爱喝水
猫主子
注意使用对象.变量名的方式为对象添加属性的方式虽然方便,但是如果函数内部使用时没有提前添加属性,程序将会报错,而且不容易排查,慎重使用
python中的初始化方法
当我们使用 类名()
创建对象时,python 解释器会自动为我们做两件事情
- 1.为对象在内存中分配空间 – 创建对象
- 2.为对象的属性设置初始值 – 初始化方法(init)
这个初始化方法,就是 init 方法 ,是对象的内置方法
init 方法是专门,用来定可以那个类 具有哪些属性的方法
代码示例
class Cat:
"""这是一个猫类"""
def eat(self):
print("%s 爱吃鱼" % self.name)
def drink(self):
print("%s 爱喝水" % self.name)
def __init__(self):
print("这是一个初始化方法")
self.name = "猫主子"
# 创建小猫对象
cat = Cat()
cat.eat()
cat.drink()
print(cat.name)
运行结果
这是一个初始化方法
猫主子 爱吃鱼
猫主子 爱喝水
猫主子
方法的有惨构造方法
开发中希望创建对象的同时就给对象设置属性,可以对 __init__
方法进行改造
- 1.把希望设置的属性值,定义成
__init__
方法的参数,如果期望有默认值可以赋值默认值 - 2.在方法内部使用
self.变量名 = 形参
接收外部传递的参数 - 3.在创建对象时,使用
类名(形参1,形参2...)
的形式调用
代码示例
class Cat:
"""这是一个猫类"""
def eat(self):
print("%s 爱吃鱼" % self.name)
def drink(self):
print("%s 爱喝水" % self.name)
def __init__(self, new_name="小猫"):
print("这是一个初始化方法")
self.name = new_name
# 创建小猫对象
cat = Cat("大脸猫")
cat.eat()
cat.drink()
print(cat.name)
运行结果
这是一个初始化方法
大脸猫 爱吃鱼
大脸猫 爱喝水
大脸猫
del 方法
-
在python中
- 当使用
类名()
创建对象时,为对象分配空间后,自动调用__init__
方法 - 当一个对象从内存中销毁前,会自动调用
__del__
方法
- 当使用
-
应用场景
- 1.
__init__
改造初始化方法可以让创建对象更加灵活 - 2.
__del__
如果希望在对象被销毁前做一些事,可以考虑使用__del__
方法
- 1.
-
生命周期
- 一个对象从调用
类名()
创建,生命周期开始,并调用__init__
方法 - 一个对象的
__del__
方法 ,一旦被调用,生命周期结束 - 在对象的生命周期内,可以访问对象的属性或者调用对象的方法
- 一个对象从调用
面向对象编程
示例
有一个房间类,房间户型,有建筑面积和室内可用面积,有家具 ,家具有自己的名称和占地面积,占地面积不可以多于房子的身剩余面积
class Furniture:
def __init__(self, name, area):
self.furnitureName = name
self.furnitureArea = area
def __str__(self):
return "%s 占地 %.2f 平方米" % (self.furnitureName, self.furnitureArea)
class House:
def __init__(self, house_type, area):
self.house_type = house_type
self.area = area
self.free_area = area
self.furniture_list = []
def __str__(self):
list = []
for item in self.furniture_list:
list.append(item.furnitureName)
return "户型 %s ,面积 %.2f【剩余%.2f】,\n家具 %s" % (self.house_type, self.area, self.free_area, list)
def add_furture(self, furture):
if furture.furnitureArea > self.free_area:
print("%s 占用面积过大无法添加" % furture.furnitureName)
return
self.furniture_list.append(furture)
self.free_area -= furture.furnitureArea
print("家具 %s 添加成功" % furture.furnitureName)
# 1.创建家具
bed = Furniture("席梦思", 60.20)
chest = Furniture("厨房", 30.10)
table = Furniture("餐桌", 45.5)
# 2.创建房子对象
my_house = House("三室一厅", 120.20)
my_house.add_furture(bed)
my_house.add_furture(chest)
my_house.add_furture(table)
print(my_house.__str__())
运行结果
家具 席梦思 添加成功
家具 厨房 添加成功
餐桌 占用面积过大无法添加
户型 三室一厅 ,面积 120.20【剩余29.90】,
家具 ['席梦思', '厨房']
在代码中如果对象的属性不知道赋值什么类型可以使用 变量=None
None
关键字表示什么都没有- 表示一个对象没有方法和属性或者一个变量没有类型
- 可以将
None
赋值给任何变量
代码示例
class Gun:
def __init__(self, model):
# 抢的类型
self.moudle = model
# 子弹数
self.bullet_count = 0
def add_bullet(self, bullet_count):
self.bullet_count += bullet_count
def shoot(self):
if self.bullet_count <= 0:
print("[%s] 没有子弹了" % self.moudle)
self.bullet_count -= 1
# 声音特效制作
print("[%s] 突突突.... 子弹剩余 %8d" % (self.moudle, self.bullet_count))
class Soldier:
def __init__(self, name):
self.name = name
self.gun = None
def add_Gun(self, gun):
self.gun = gun
def fire(self):
if self.gun==None:
print("[%s] 还没有枪...")
return
# 喊口号
print("冲啊 [%s]" % self.name)
# 让枪装填子弹
if self.gun.bullet_count==0:
self.gun.add_bullet(50)
# 开火
self.gun.shoot()
xusanduo = Soldier("许三多")
xusanduo.add_Gun(Gun("Ak47"))
xusanduo.fire()
xusanduo.fire()
xusanduo.fire()
xusanduo.fire()
运行结果
冲啊 [许三多]
[Ak47] 突突突.... 子弹剩余 49
冲啊 [许三多]
[Ak47] 突突突.... 子弹剩余 48
冲啊 [许三多]
[Ak47] 突突突.... 子弹剩余 47
冲啊 [许三多]
[Ak47] 突突突.... 子弹剩余 46
总结:
- 封装是面向对象的编程的一大特点
- 面向对象的第一步就是讲属性和方法封装到一个类中
- 外界使用类创建对象,然后让对象调用方法
- 类的实现细节应该封装在类的内部,外界无需直到实现的具体,只需要通过接口进行调用
python中的身份身份运算符
身份运算符用于比较两个对象的 地址 是否一致,是否是同一个对象的引用
- 在python中 针对
None
比较时 , 建议使用is
判断
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用同一个对象 | x is y ,类似 id(x) == id(y) |
is not | is not 是判断两个标识符是不是引用不同对象 | x is not y ,类似 id(x) != id(y) |
- is与 == 的区别
- is 用于判断 两个变量引用的对象是不是同一个
- == 用于判断 引变量的值 是否相等
代码示例
a = [1, 2, 3]
b = [1, 2, 3]
print("a is b %s" % (a is b))
print("a == b %s" % (a == b))
运行结果
a is b False
a == b True
私有属性和私有方法
- 私有属性 就是 对象不希望公开的属性
- 私有方法 就是 对象不希望公开的方法
在定义属性和方法时,在 属性 或者 方法 的前面增加两个下划线,定义的就是私有方法或者属性
代码示例
class Women:
def __init__(self, name):
self.name = name
# 变量的前面添加两个下划线,定义的属性为私有属性
self.__age = 18
# 在类的内部,是可以访问对象的私有属性的
def secret(self):
print("%s 的年龄是 %d"% (self.name,self.__age))
xiaohong = Women("小红")
xiaohong.secret()
# 类的外部是不可以直接访问私有类的属性的
print("%s 的年龄是 %d" % (xiaohong.name, xiaohong.__age))
运行代码
小红 的年龄是 18
File "E:/学习和总结/groovyStudy/python实战代码/newcode/venv/Include/soldiers_raided.py", line 61, in <module>
print("%s 的年龄是 %d" % (xiaohong.name, xiaohong.__age))
AttributeError: 'Women' object has no attribute '__age'
伪私有属性和伪私有方法的访问
-
在python中是没有真正意义上的私有实行和私有方法的,我们依旧,可以通过
_类名_变量名
或者_类名_方法名
的方式进行访问的 -
在给
属性、方法
命名时,实际上是对名称做了特殊处理,使得外界无法访问 -
处理方式 在名称前面加上
_类名
得到_类名_变量名
代码示例
class Women:
def __init__(self, name):
self.name = name
self.__age = 18
def secret(self):
print("%s 的年龄是 %d" % (self.name, self.__age))
def __printName(self):
print(self.name)
xiaohong = Women("小红")
xiaohong.secret()
print("%s 的年龄是 %d" % (xiaohong.name, xiaohong._Women__age))
xiaohong._Women__printName()
运行结果
小红 的年龄是 18
小红 的年龄是 18
小红