Python_封装案例(士兵突击)

1. 需求分析-属性可以是另一个类创建的对象

 

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

许三多是一个士兵, 所以我们需要定义一个 士兵类Soldier , 而AK47 是一把枪, 因此我们还需要定义一个枪类,两个类确定之后, 我们在看一下需求, 有一把AK47, 意味着许三多应该有一个枪的属性, 这把AK47 应该是由枪类Gun 创建出来的对象。

士兵许三多的gun(AK47)的属性使用枪类创建出来的对象, 士兵可以开火, 枪能够发射子弹, 士兵开火是许三多举起gun(AK47)扣动扳机, 这个是开火的动作, 而枪发射子弹是把子弹发射出去, 因此我们需要在士兵类中, 定义一个开火的方法, 而在枪类中, 定义一个发射的方法, 枪发射的是子弹, 士兵开火扣动的是扳机, 两个方法的动作还是有所区别的.

为了简化案例演练, 暂时不考虑子弹这个类, 只考虑一下子弹的数量, 枪要想发射子弹, 应该有足够数量的子弹, 因此我们还需要再枪类中再定义子弹数量这个属性, 同时再给枪增加一个装填子弹的方法add_bullet, 我们给这个方法传递一个要装填子弹的数量count, 这个数量就可以来修改枪这个对象中现在包含的子弹数量, 当枪有了足够多的子弹, 就可以进行发射的动作.

以上就是我们要做的士兵突击案例的需求.

我们应该先开发枪类, 枪类先被使用到, 否则我们再开发士兵类的时候, 如果没有枪类, 士兵的属性都定义不了, 因此我们应该先把重点放在枪类的开发.

2.创建枪类

使用class 关键字创建一个枪类, 然后使用def 关键字定义初始化方法, 初始化方法可以简化对象的创建, 枪类中需要定义两个属性, 型号model, 子弹数量 bullet_count .

第一个属性型号model, 应该由外界传递, 第二个属性 子弹数量 bullet_count,假设我们每建立一个枪的对象, 初始的子弹数量都为0, 枪要想发射子弹, 就必须调用装填子弹这个方法, 才能发射, 那么从这个角度来看, 子弹数量这个属性, 我们不需要定义成初始化方法的形参(也就是由外界传递).

给初始化方法增加一个型号model的形参, 然后在初始化方法中定义两个属性, 第一个属性是枪的型号model, 第二个属性我们再来指定一下子弹数量 bullet_count.

使用self.model  = model, 把形参model 传递给属性, 然后, 定义子弹数量 bullet_count 的属性, 并把枪的子弹数量初始设置为0, 这样一个初始化方法就完成了.

在枪类中有个装填子弹的方法, 这个方法需要接收一个count 的参数, 因为我们需要使用这个参数来修改子弹数量 bullet_count 这个属性.

使用def 关键字定义一个增加子弹的方法, 这个方法只需要把子弹数量的属性增加一下就可以, 那么我们就在方法内部让子弹数量 bullet_count 与传递进来的形参count做一个相加, self.bullet_count += count, 这样装填子弹的方法就写完了.

枪应该能够发射子弹, 只要子弹的数量足够, 枪就能够发射子弹, 因此shoot 方法并不需要传递任何的参数, 那么就使用def 关键字来定义一个shoot 方法, 这个方法并不需要传递额外的参数.

枪要发射子弹应该做三件事情 , 第一件事情应该判断子弹数量, 第二件事情是发射子弹, 每一次发射子弹后, 然子弹的数量做一个减1 的操作, 第三件事情是发射完子弹之后, 要提示一下发射信息.

第一件事情, 要判断先写一个if, 判断枪对象的子弹数量属性, 如果子弹数量 <= 0, 就不能发射了, 使用print函数做一个输出, print("[%s] 没有子弹了..." % self.model), 如果没有子弹了, 下方第二, 第三步代码就不需 要执行了, 既然不需要执行下方的代码, 我们就可以使用return 关键字直接返回.

第二步, 要想发射子弹, 把子弹的数量减1, self.bullet_count -= 1. 子弹数量就修改完成了.

第三步, 我们再使用print 函数做一个输出, print("[%s] 突突突...[%d]" % (self.model, self.bullet_count)), 第一个格式操作符, 我们应该传入型号model, 第二个格式操作符应该传入剩余的子弹数量self.bullet_count.

经过以上三步, 一个发射方法也完成了.

枪类已经完成了, 我们就可以在主程序中来创建枪对象.

创建一个枪对象ak47, 先让它调用一下装填子弹的方法,指定50发子弹, 再让它调用一下发射的方法, ak47.shoot(), 控制台输出了"[AK47] 突突突...[49]", 发射了1发子弹, 剩余49发子弹.

class Gun:


    def __init__(self, model):
        #1. 枪的型号model
        self.model = model

        #2. 子弹的数量, 把枪的子弹数量初始值设置为0
        self.bullet_count = 0

    # 定义一个装填子弹的方法, 传入形参count, 表示装填子弹的方法 
    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. 提示发射信息, 把枪的型号model和剩余子弹bullet_count 做一个输出
    
        print("[%s] 突突突...[%d]" % (self.model, self.bullet_count))

# 枪类已经创建完成, 就可以在主程序中创建枪对象

# 1. 创建枪对象, 创建一个 叫ak47 的对象
ak47 = Gun("AK47")

# 给ak47 装填子弹
ak47.bullet_count(50)

# 使用 ak47 发射子弹
ak47.shoot()




运行结果:

 

3. 创建士兵类_完成初始化方法

 

接下来就设置一下士兵类, 我们就在士兵类的初始化方法中, 给士兵定义两个属性, 一个姓名name, 一个枪gun,

假设每一个新兵都没有枪, 我们需要再初始化方法中使用赋值语句来定义枪的属性, 但是新兵没有枪, 就不能使用一个枪对象赋值给gun 这个属性, 在开发时, 如果定义一个属性的时候, 不知道给这个属性设置什么初始值, 这个时候,我们就可以在赋值语句的右侧使用 None 这个关键字, 在Python中, None 这个关键字就表示什么都没有, 准确来讲, None 时一个空对象, 这个空对象是一个没有任何方法和属性的特殊对象.

先来定义一个士兵类Soldier, 使用def 关键字找到初始化方法__init__ , 初始化方法可以通过形参来简化对象的创建, 士兵的姓名属性name 可以当作形参传递, 新兵没有枪, 意味着我们并不需要枪来定义一个形参, 先给士兵定义一个name 的属性, self.name = name, 然后再给士兵定义一个 枪的属性, self.gun = None , 因为新兵没有枪, 所以不能使用其他的枪对象来给这个枪属性进行赋值, 所以我们就直接使用None 关键字, 既定义属性, 又不设置具体的枪对象, 两个属性定义完成, 初始化方法就定义完成了.

现在来创建一个许三多的士兵, 调用一下Soldier类 来创建一个士兵对象, 叫xusanduo, 创建完成之后, 就是用print 函数把xusanduo 的枪的属性做一个输出, print(xusanduo.gun), 运行后,控制台输出了None, 和我们再初始化方法中指定的值时完全一样的(self.gun = None), xusanduo 的枪是一个空对象, 就说明xusanduo 现在没有枪,

class Gun:


    def __init__(self, model):
        #1. 枪的型号model
        self.model = model

        #2. 子弹的数量, 把枪的子弹数量初始值设置为0
        self.bullet_count = 0

    # 定义一个装填子弹的方法, 传入形参count, 表示装填子弹的方法 
    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. 提示发射信息, 把枪的型号model和剩余子弹bullet_count 做一个输出
    
        print("[%s] 突突突...[%d]" % (self.model, self.bullet_count))


# 定义一个士兵类 
class Soldier:
    # 初始化方法可以通过传入形参来简化对象的创建
    def __init__(self, name):
        # 1.定义新兵的姓名
        self.name = name

        #2.定义枪的属性, 新兵没有枪, 在等号右侧如果不知道设置什么初始值, 可以使用None这个关键字, 既定义属性, 有不设置具体的枪对象
        self.gun = None
        # 初始化方法定义完成






# 枪类已经创建完成, 就可以在主程序中创建枪对象

# 1. 创建枪对象, 创建一个 叫ak47 的对象
ak47 = Gun("AK47")

# 给ak47 装填子弹
ak47.add_bullet(50)

# 使用 ak47 发射子弹
ak47.shoot()

# 1.创建一个叫xusanduo 的士兵
xusanduo = Soldier("许三多")

# 把xusanduo 这个对象枪的属性做一个输出, 控制台输出了 None, 说明了xusanduo 的枪是一个空对象,就说明xusanduo 现在没有枪
print(xusanduo.gun)








运行结果:

 

可以在主程序中使用赋值语句给xusanduo 设置一把枪, 我们就把之前创建的 ak47 交给xusanduo,  用赋值语句把 ak47 交给xusanduo, 控制台输出了枪对象和内存地址, 现在士兵xusanduo 就有了一把ak47. 

class Gun:


    def __init__(self, model):
        #1. 枪的型号model
        self.model = model

        #2. 子弹的数量, 把枪的子弹数量初始值设置为0
        self.bullet_count = 0

    # 定义一个装填子弹的方法, 传入形参count, 表示装填子弹的方法 
    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. 提示发射信息, 把枪的型号model和剩余子弹bullet_count 做一个输出
    
        print("[%s] 突突突...[%d]" % (self.model, self.bullet_count))


# 定义一个士兵类 
class Soldier:
    # 初始化方法可以通过传入形参来简化对象的创建
    def __init__(self, name):
        # 1.定义新兵的姓名
        self.name = name

        #2.定义枪的属性, 新兵没有枪, 在等号右侧如果不知道设置什么初始值, 可以使用None这个关键字, 既定义属性, 有不设置具体的枪对象
        self.gun = None
        # 初始化方法定义完成






# 枪类已经创建完成, 就可以在主程序中创建枪对象

# 1. 创建枪对象, 创建一个 叫ak47 的对象
ak47 = Gun("AK47")

# 给ak47 装填子弹
ak47.add_bullet(50)

# 使用 ak47 发射子弹
ak47.shoot()

# 1.创建一个叫xusanduo 的士兵
xusanduo = Soldier("许三多")

# 把xusanduo 这个对象枪的属性做一个输出, 控制台输出了 None, 说明了xusanduo 的枪是一个空对象,就说明xusanduo 现在没有枪
print(xusanduo.gun)

# 用赋值语句和gun 这个属性把 ak47 交给xusanduo
xusanduo.gun = ak47
# 控制台会输出枪对象和对象的内存地址
print(xusanduo.gun)







运行结果:

如果想要修改属性的值, 我们再在主程序中使用赋值语句给这个属性设置一个新对象就可以了.

使用赋值语句给gun 这个属性设置一个新对象, gun 属性原来是空对象 None

 

4.完成开火方法def fire().

接下来我们就共同实现一下士兵开枪的方法,看一下主程序, 先是创建了一个枪对象, 然后想让枪自己装填子弹 ak47.add_bullet, 想让枪自己发射子弹ak47.shoot, 但枪不能自己装填子弹, 枪自己也不能发射子弹, 需要xusanduo来扣动扳机.

现在把光标移动到士兵类中, 再一次使用def 关键字来定义一个开枪的方法, def fire, 然后把光标移动到方法内部, 一个士兵要开枪, 第一件事情就是判断一下士兵有没有枪, 士兵没有枪就不能射击, 士兵有了枪之后,第二件事,让士兵高喊口号,第三件事,让枪装填子弹,第四件事,发射子弹。第一,判断士兵的枪是不是一个空对象,如果等于None,就说明士兵还没有枪。没有枪,就使用print 函数提示一下,并把没枪士兵的名字做一个输出。没有枪,第二,三,四步的代码都不需要执行了。既然不需要,就直接使用return 直接返回就可以了。

如果士兵有枪,就继续执行第二步,同样,使用print 函数把士兵的名字也做一个输出。

第三步,使用self.gun 找到士兵自己的枪,再使用士兵自己的枪来调用一下添加子弹的方法,装填50发, self.gun. add_bullet.

第四步, 让枪发射子弹, self.gun.shoot, 让xusanduo 调用一下开枪的方法, 运行一下程序, xusanduo 高喊[冲啊], 然后[AK47] 突突突, 突突突完了之后子弹的数量减1, 只剩49发子弹, 开枪的方法已经完成了.

回顾:在主程序中, 我们创建了两个对象, 一个枪对象, 一个士兵对象, 同时把ak47 这个对象设置给了士兵的枪属性, 设置完成之后, 我们再让士兵调用开枪的方法, 主程序中只有四句代码.

创建枪对象 > Gun("AK47")

创建许三多 > xusanduo = Soldier("许三多")

把ak47 这个对象设置给了士兵的枪属性 > xusanduo.gun = ak47

让xusanduo 调用一下开枪的方法 > xusanduo.fire()

面向对象开发最重要的特点就是创建对象, 让对象调用方法, 而方法的具体实现细节全部被封装再类的内部.

我们要想装填子弹, 直接让枪调用一下已经在类中封装好的方法,要想发射子弹, 同样是让枪调用一下已经封装好的发射好的方法.

class Gun:


    def __init__(self, model):
        #1. 枪的型号model
        self.model = model

        #2. 子弹的数量, 把枪的子弹数量初始值设置为0
        self.bullet_count = 0

    # 定义一个装填子弹的方法, 传入形参count, 表示装填子弹的方法 
    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. 提示发射信息, 把枪的型号model和剩余子弹bullet_count 做一个输出
    
        print("[%s] 突突突...[%d]" % (self.model, self.bullet_count))


# 定义一个士兵类 
class Soldier:
    # 初始化方法可以通过传入形参来简化对象的创建
    def __init__(self, name):
        # 1.定义新兵的姓名
        self.name = name

        #2.定义枪的属性, 新兵没有枪, 在等号右侧如果不知道设置什么初始值, 可以使用None这个关键字, 既定义属性, 有不设置具体的枪对象
        self.gun = None
        # 初始化方法定义完成

    # 定义一个开枪的方法
    def fire(self):
        # 1. 判断士兵是否有枪
        if self.gun == None:
            print("[%s] 还没有枪..." % self.name)

            return

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


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


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





        







# 枪类已经创建完成, 就可以在主程序中创建枪对象

# 1. 创建枪对象, 创建一个 叫ak47 的对象
ak47 = Gun("AK47")


# 1.创建一个叫xusanduo 的士兵
xusanduo = Soldier("许三多")



# 用赋值语句和gun 这个属性把 ak47 交给xusanduo
xusanduo.gun = ak47
# 士兵开枪
xusanduo.fire()
# 控制台会输出枪对象和对象的内存地址
print(xusanduo.gun)







运行结果:

 

5. 身份运算符

 

PEP 8 是python 的编码规范, 提示我们在跟None 比较的时候, 应该使用if 这个运算符, is 这个运算符就是python 中的身份运算符.

在 python 中, 有两个身份运算符, 一个是 is , 一个是 is not, 从字面看, 这两个身份运算符的作用是刚好相反的.

在python 中, 使用身份运算符, 可以比较两个对象的内存地址是否一致.

id 这个函数可以来查看一个数据的内存地址, 而使用 is 来进行判断的时候, 实际上就是在比较两个变量的内存地址是否一致, id(x) == id(y), 用我们之前学习的引用概念来讲, 就是来判断这两个变量引用的是否是同一个对象.

在python 中, 数据和变量是分别存储的, 我们把数据看出内存中的小格子, 然后把变量看出一个标签, 譬如有一个x 的变量, 有一个 y 的变量, 然后让这个两个变量同时贴在同一个小格子上, 如果是这种情况, 我们使用is 这个身份运算符判断, x 和 y 就是相等的, 这个就是身份运算符的作用.

is 这个身份运算符是用来判断两个变量引用的对象是否是同一个, 而 == 呢, 是用来判断两个变量的值是否相等.

先定义一个列表a = [1,2,3], 使用id函数来查看一下列表a的内存地址,再定义一个列表b = [1,2],使用id函数来查看一下列表b的内存地址,现在列表a和b的内容和内存地址都不一样。现在给b列表追加一个数据3,使b = [1,2,3], 然后使用 == 来比较一下这两个变量, 回车后返回是 True, 这意味着列表a 和 b 的内容是完全相等的.

 

如果使用is 这个身份运算符, 返回 False, 因为列表a 和 b 的内存地址并不相同, 这就是 is 和 == 的区别.

 

针对None 进行比较的时候, None 是一个空对象, 建议使用 is 来判断, 而不要使用等等, 当然, 如果使用 == , 程序的执行效果不会有任何的问题, 因为都是空列表, 都没有内容,只是按照PEP 8 的编码规范, 建议我们使用 is 来判断.

class Gun:


    def __init__(self, model):
        #1. 枪的型号model
        self.model = model

        #2. 子弹的数量, 把枪的子弹数量初始值设置为0
        self.bullet_count = 0

    # 定义一个装填子弹的方法, 传入形参count, 表示装填子弹的方法 
    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. 提示发射信息, 把枪的型号model和剩余子弹bullet_count 做一个输出
    
        print("[%s] 突突突...[%d]" % (self.model, self.bullet_count))


# 定义一个士兵类 
class Soldier:
    # 初始化方法可以通过传入形参来简化对象的创建
    def __init__(self, name):
        # 1.定义新兵的姓名
        self.name = name

        #2.定义枪的属性, 新兵没有枪, 在等号右侧如果不知道设置什么初始值, 可以使用None这个关键字, 既定义属性, 有不设置具体的枪对象
        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 的对象
ak47 = Gun("AK47")


# 1.创建一个叫xusanduo 的士兵
xusanduo = Soldier("许三多")



# 用赋值语句和gun 这个属性把 ak47 交给xusanduo
xusanduo.gun = ak47
# 士兵开枪
xusanduo.fire()
# 控制台会输出枪对象和对象的内存地址
print(xusanduo.gun)







 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值