Python 面向对象系列(二)

01 封装

  1. 封装 是面向对象编程的一大特点
  2. 面向对象编程的 第一步 —— 将 属性方法 装 到一个抽象的
  3. 外界 使用 创建 对象,然后 让对象调用方法
  4. 对象方法的细节 都被 封装类的内部

一个对象的 属性 可以是 另外一个类创建的对象

02 小明爱跑步案例

需求

  1. 小明 体重 75.0 公斤
  2. 小明每次 跑步 会减肥0.5 公斤
  3. 小明每次 吃东西 体重增加 1 公斤
属性方法
Personname
weight
__ init __(self,name,weight):
__ str __(self):
run(self):
eat(self):

提示:在 对象的方法内部,是可以 直接访问对象的属性 的!

代码实现

class Person:

    def __init__(self, name, weight):
        # self.属性 = 形参
        self.name = name
        self.weight = weight

    def __str__(self):
        return "我的名字叫 %s 体重是 %.2f 公斤" % (self.name, self.weight)

    def run(self):
        print("%s 爱跑步,跑步锻炼身体" % self.name)
        self.weight -= 0.5

    def eat(self):
        print("%s 是吃货,吃完这顿在减肥" % self.name)
        self.weight += 1


xiaoming = Person("小明", 75.0)

xiaoming.run()
xiaoming.eat()

print(xiaoming)

输出结果

小明 爱跑步,跑步锻炼身体
小明 是吃货,吃完这顿在减肥
我的名字叫 小明 体重是 75.50 公斤

2.1 小明爱跑步案例扩展 – 小美也爱跑步

需求

  1. 小明小美 都爱跑步
  2. 小明 体重 75.0 公斤
  3. 小美 体重 45.0 公斤
  4. 每次 跑步 会减肥0.5 公斤
  5. 每次 吃东西 体重增加 1 公斤
属性方法
Personname
weight
__ init __(self,name,weight):
__ str __(self):
run(self):
eat(self):

提示:

  1. 对象的方法内部,是可以 直接访问对象的属性
  2. 同一个 创建的 多个对象 之间,属性 互不干扰

代码实现

class Person:

    def __init__(self, name, weight):
        # self.属性 = 形参
        self.name = name
        self.weight = weight

    def __str__(self):
        return "我的名字叫 %s 体重是 %.2f 公斤" % (self.name, self.weight)

    def run(self):
        print("%s 爱跑步,跑步锻炼身体" % self.name)
        self.weight -= 0.5

    def eat(self):
        print("%s 是吃货,吃完这顿在减肥" % self.name)
        self.weight += 1


xiaoming = Person("小明", 75.0)

xiaoming.run()
xiaoming.eat()

print(xiaoming)

xiaomei = Person("小美", 45.0)
xiaomei.eat()
xiaomei.run()

print(xiaomei)
print(xiaoming)

输出结果

小明 爱跑步,跑步锻炼身体
小明 是吃货,吃完这顿在减肥
我的名字叫 小明 体重是 75.50 公斤
小美 是吃货,吃完这顿在减肥
小美 爱跑步,跑步锻炼身体
我的名字叫 小美 体重是 45.50 公斤
我的名字叫 小明 体重是 75.50 公斤

03 摆放家具案例

需求

  1. 房子(House)户型、总面积家具名称列表
    • 新房子没有任何的家具
  2. 家具(HouseItem)名字占地面积,其中
    • 席梦思(bed) 占地 4 平米
    • 衣柜(chest) 占地 2 平米
    • 餐桌(table) 占地 1.5 平米
  3. 将以上三件 家具 添加房子
  4. 打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表

3.1 需求分析,被使用类的应该先开发

属性方法
HouseItemname
area
__ init __(self,name,area):
__ str __(self):
Househouse_type
area
free_area
item_list
__ init __(self,house_type,area):
__ str __(self):
add_item(self,item):

剩余面积

  1. 在创建房子对象时,定义一个 剩余面积的属性、初始值和总面积相等
  2. 当调用 add_item 方法,向房间 添加家具 时,让 剩余面积 -= 家具面积
    思考:应该先开发哪一个类?
    答案 —— 家具类
  3. 家具简单
  4. 房子要使用到家具,被使用的类,通常应该先开发

3.2 家具类以及创建家具对象

代码实现

class HouseItem:

    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return "[%s] 占地 %.2f" % (self.name, self.area)


# 1、创建家具
bed = HouseItem("席梦思", 4)
chest = HouseItem("衣柜", 2)
table = HouseItem("餐桌", 1.5)

print(bed)
print(chest)
print(table)

输出结果

[席梦思] 占地 4.00
[衣柜] 占地 2.00
[餐桌] 占地 1.50

小结

  1. 创建了一个 家具类,使用到 __ init __ __ str __ 两个内置方法
  2. 使用 家具类 创建了三个家具对象

3.3 定义房子类

代码实现

class HouseItem:

    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return "[%s] 占地 %.2f" % (self.name, self.area)


class House:

    def __init__(self, house_type, area):
        self.house_type = house_type
        self.area = area

        # 剩余面积
        self.free_area = area

        # 家具名称列表
        self.item_list = []

    def __str__(self):
        # Python 能够自动的将一对括号内部的代码连接在一起
        return ("户型:%s\n总面积:%.2f[剩余面积:%.2f]\n家具:%s"
                % (self.house_type, self.area,
                   self.free_area, self.item_list))

    def add_item(self, item):
        print("要添加 %s " % item)


# 1、创建家具
bed = HouseItem("席梦思", 4)
chest = HouseItem("衣柜", 2)
table = HouseItem("餐桌", 1.5)

print(bed)
print(chest)
print(table)

# 2.创建房子对象
my_home = House("两室一厅", 80)

my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)

print(my_home)

输出结果

[席梦思] 占地 4.00
[衣柜] 占地 2.00
[餐桌] 占地 1.50
要添加 [席梦思] 占地 4.00
要添加 [衣柜] 占地 2.00
要添加 [餐桌] 占地 1.50
户型:两室一厅
总面积:80.00[剩余面积:80.00]
家具:[]

小结

  1. 创建了一个 房子类,使用到 __ init __ __ str __ 两个内置方法
  2. 准备了一个 add_item 方法 准备添加家具
  3. 使用 房子类 创建了一个房子对象
  4. 房子对象 调用了三次 add_item 方法 方法,将 三件家具 以实参传递到 add_item 方法 内部

3.4 添加家具

需求

  1. 判断 家具面积 是否 超过剩余面积如果超过,则提示不能添加这件家具
  2. 家具名称 追加到 家具名称列表
  3. 房子的剩余面积 - 家具面积

代码实现

class HouseItem:

    def __init__(self, name, area):
        self.name = name
        self.area = area

    def __str__(self):
        return "[%s] 占地 %.2f" % (self.name, self.area)


class House:

    def __init__(self, house_type, area):
        self.house_type = house_type
        self.area = area

        # 剩余面积
        self.free_area = area

        # 家具名称列表
        self.item_list = []

    def __str__(self):
        # Python 能够自动的将一对括号内部的代码连接在一起
        return ("户型:%s\n总面积:%.2f[剩余面积:%.2f]\n家具:%s"
                % (self.house_type, self.area,
                   self.free_area, self.item_list))

    def add_item(self, item):

        print("要添加 %s " % item)
        # 1. 判断家具的面积
        if item.area > self.free_area :
            print("%s 的面积太大了,无法添加" % item.name)
            return

        # 2. 将家具的名称添加到列表中
        self.item_list.append(item.name)

        # 3. 计算剩余面积
        self.free_area -= item.area


# 1、创建家具
bed = HouseItem("席梦思", 40)
chest = HouseItem("衣柜", 2)
table = HouseItem("餐桌", 1.5)

print(bed)
print(chest)
print(table)

# 2.创建房子对象
my_home = House("两室一厅", 80)

my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)

print(my_home)

输出结果

[席梦思] 占地 40.00
[衣柜] 占地 2.00
[餐桌] 占地 1.50
要添加 [席梦思] 占地 40.00
要添加 [衣柜] 占地 2.00
要添加 [餐桌] 占地 1.50
户型:两室一厅
总面积:80.00[剩余面积:36.50]
家具:[‘席梦思’, ‘衣柜’, ‘餐桌’]

小结

  1. 主程序只负责创建 房子 对象 和 家具 对象
  2. 房子 对象调用 add_item 方法 方法 将家具添加到房子
  3. 面积计算、剩余面积、家具列表 等处理都被 封装房子类的内部

04 士兵突击案例

需求

  1. 士兵 许三多 有一把 AK47
  2. 士兵 可以 开火
  3. 能够 发射 子弹
  4. 能够 填装子弹 —— 增加子弹数量
属性方法
Soldiername
gun
__ init __(self,name,area):
fire(self):
Gunmodel
bullet_count
__ init __(self,house_type,area):
add_bullet(self,count):
shoot(self):

4.1 开发抢类

代码实现

class Gun:

    def __init__(self, model):

        # 1. 抢的型号
        self.model = model

        # 2. 子弹数量
        self.bullet_count = 0

    def add_bullet(self, count):

        self.bullet_count += count

    def shoot(self):

        # 1. 判断子弹数量
        if self.bullet_count <= 0:
            print("[%s]没有子弹了" % self.model)
            return

        # 2. 发射子弹,-1
        self.bullet_count -= 1

        # 3. 提示发射信息
        print("[%s]突突突...[%d]" % (self.model, self.bullet_count))


# 1. 创建抢对象
ak47 = Gun("AK-47")

ak47.add_bullet(100)
ak47.shoot()

输出结果

[AK-47]突突突…[99]

4.2 开发士兵类

假设:每一个新兵 都 没有抢

定义没有初始值的属性
在定义属性时,如果 不知道设置什么初始值,可是设置为 None

  • None 关键字 表示 什么都没有
  • 表示一个 空对象,没有属性和方法,是一个特殊的常量
  • 可以将None赋值给任何一个变量

fire方法需求

  1. 判断是否有抢,没有抢没法冲锋
  2. 喊一声口号
  3. 装填子弹
  4. 射击

代码实现

class Gun:

    def __init__(self, model):

        # 1. 枪的型号
        self.model = model

        # 2. 子弹数量
        self.bullet_count = 0

    def add_bullet(self, count):

        self.bullet_count += count

    def shoot(self):

        # 1. 判断子弹数量
        if self.bullet_count <= 0:
            print("[%s]没有子弹了" % self.model)
            return

        # 2. 发射子弹,-1
        self.bullet_count -= 1

        # 3. 提示发射信息
        print("[%s]突突突...[%d]" % (self.model, self.bullet_count))


class Soldier:

    def __init__(self, name):

        # 1.姓名
        self.name = name
        # 1.枪-新兵没有抢
        self.gun = None

    def fire(self):

        # 1.判断士兵是否有抢
        if self.gun is None:
            print("[%s] 还没有抢..." % self.name)

            return

        # 2.高喊口号
        print("冲啊...[%s]" % self.name)

        # 3.让抢装填子弹
        self.gun.add_bullet(50)

        # 4.让抢发射子弹
        self.gun.shoot()


# 1. 创建枪对象
ak47 = Gun("AK-47")

# 2. 创建许三多
xusanduo = Soldier("许三多")

xusanduo.gun = ak47
xusanduo.fire()

print(xusanduo.gun)

输出结果

冲啊…[许三多]
[AK-47]突突突…[49]
<main.Gun object at 0x0000022DD8586A60>

05 身份运算符

身份运算符用于 比较 两个对象的 内存地址 是否一致 – 是否是对同一个对象的引用
Python中针对None 比较时,建议使用is判断

运算符描述实例
isis是判断两个标识符是不是引用同一个对象x is y,类似 id(x)==id(y)
is notis not是判断两个标识符是不是引用不同对象x is not y,类似 id(x)!=id(y)

is 与 == 区别:
is 用于判断 两个变量 引用对象是否为同一个
== 用于判断 引用变量的值 是否相等

a = [1, 2, 3]
b = [1, 2, 3]
b is a
Flase
b == a
True

06 私有属性和私有方法

6.1 应用场景及定义方式

应用场景

  • 在实际开发中,对象 的 某个属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到
  • 私有属性 就是 对象 不希望公开的 属性
  • 私有方法 就是 对象 不希望公开的 方法
    定义方式
  • 定义属性或方法时,在 属性名或者方法名 前 增加 两个下划线,定义的就是 私有 属性和方法
Women
name   __ age
__ init __ (self,name) :    __secret(self):
class Women:

    def __init__(self,name):

        self.name = name
        self.__age = 18

    def __secret(self):
        # 在对象的方法内部,是可以访问对象的私有属性的
        print("%s 的年龄是 %d" % (self.name, self.__age))


xiaofang = Women("小芳")

# 私有属性,在外界不能直接被访问
# print(xiaofang.__age)
# 私有方法,同样不允许在外界直接被访问
# xiaofang.__secret()

6.2 伪私有属性和私有方法(科普)

提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法
Python中,并没有真正意义私有

  • 在给 属性、方法命名时,实际是对 名称 做了一些特殊处理,是的外界无法访问到
  • 处理方式:在名称前面加上 _类名 => _类名_名称
# 私有属性,在外界不能直接被访问
print(xiaofang._Women__age)
# 私有方法,同样不允许在外界直接被访问
xiaofang._Women__secret()
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值