【Python】小甲鱼课后习题第36、37讲--类和对象(上)

问答题


1. 类和对象是什么关系呢?

答:类和对象的关系就如同模具和用这个模具制作出的物品之间的关系。一个类为它的全部对象给出了一个统一的定义,而他的每个对象则是符合这种定义的一个实体,因此类和对象的关系就是抽象和具体的关系。

3. 类的定义有些时候或许不那么“拟物”,有时候会抽象一些,例如我们定义一个矩形类,那你会为此添加哪些属性和方法呢?

答:属性可以是长和宽,方法可以是计算周长、面积等。

4*. 类的属性定义应该尽可能抽象还是尽可能具体?

答:正确的做法是应该尽可能的抽象,因为这样更符合面向对象的思维。

5*. 请用一句话概括面向对象的几个特征?

答:

特性描述
封装对外部隐藏对象的工作细节
继承子类自动共享父类之间数据和方法的机制
多态可以对不同类的对象调用相同的方法,产生不同的结果

6. 函数和方法有什么区别?

答:方法跟函数其实几乎完全一样,但有一点区别是方法默认有一个 self 参数。


0. 以下代码体现了面向对象编程的什么特征?

>>> "FishC.com".count('o')
1
>>> [1, 1, 2, 3, 5, 8].count(1)
2
>>> (0, 2, 4, 8, 12, 18).count(1)
0

答:体现了面向对象编程的多态特征。

2. self 参数的作用是什么?

答:绑定方法,据说有了这个参数,Python 再也不会傻傻分不清是哪个对象在调用方法了,你可以认为方法中的 self 其实就是实例对象的唯一标志。

3*. 如果我们不希望对象的属性或方法被外部直接引用,我们可以怎么做?

答:我们可以在属性或方法名字前边加上双下划线,这样子从外部是无法直接访问到,会显示AttributeError错误。

>>> class Person:
        __name = '小甲鱼'
        def getName(self):
                return self.__name

>>> p = Person()
>>> p.__name
Traceback (most recent call last):
  File "<pyshell#56>", line 1, in <module>
    p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> p.getName()
'小甲鱼'

我们把getName方法称之为“访问器”。Python事实上是采用一种叫“name mangling”技术,将以双下划线开头的变量名巧妙的改了个名字而已,我们仍然可以在外部通过“_类名__变量名”的方式访问:

>>> p._Person__name'小甲鱼'

4. 类在实例化后哪个方法会被自动调用?

答:__init__方法会在类实例化时被自动调用,我们称之为魔法方法。你可以重写这个方法,为对象定制初始化方案。

5*. 请解释下边代码错误的原因:

class MyClass:
        name = 'FishC'
        def myFun(self):
                print("Hello FishC!")
                
>>> MyClass.name
'FishC'
>>> MyClass.myFun()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    MyClass.myFun()
TypeError: myFun() missing 1 required positional argument: 'self'
>>>

答:首先你要明白类、类对象、实例对象是三个不同的名词。

我们常说的类指的是类定义,由于“Python无处不对象”,所以当类定义完之后,自然就是类对象。在这个时候,你可以对类的属性(变量)进行直接访问(MyClass.name)。

一个类可以实例化出无数的对象(实例对象),Python 为了区分是哪个实例对象调用了方法,于是要求方法必须绑定(通过 self 参数)才能调用。而未实例化的类对象直接调用方法,因为缺少 self 参数,所以就会报错。


动动手


0. 按照以下提示尝试定义一个 Person 类并生成类实例对象。

属性:姓名(默认姓名为“小甲鱼”)
方法:打印姓名
提示:方法中对属性的引用形式需加上 self,如 self.name

答:代码如下:

class Person:
    def __init__(self):
        self.name="小甲鱼"

    def print_name(self):
        print(self.name)
        

person=Person()
person.print_name()

1. 按照以下提示尝试定义一个矩形类并生成类实例对象。

属性:长和宽
方法:设置长和宽 -> setRect(self),获得长和宽 -> getRect(self),获得面积 -> getArea(self)
提示:方法中对属性的引用形式需加上 self,如 self.width

程序截图:
在这里插入图片描述
答:代码如下:

class Rectangle:
    def __init__(self):
        self.length=5.00
        self.width=4.00

    def getRect(self):
        print(f"这个矩形的长是:{self.length},宽是:{self.width}")

    def setRect(self):
        print("请输入矩形的长和宽...")
        self.length=float(input("长:"))
        self.width=float(input("宽:"))

    def getArea(self):
        print(self.length*self.width)

rect=Rectangle()
rect.getRect()
rect.setRect()
rect.getRect()
rect.getArea()

0*. 按照以下要求定义一个游乐园门票的类,并尝试计算2个成人+1个小孩平日票价。

  • 平日票价100元
  • 周末票价为平日的120%
  • 儿童半票

答:代码如下:

class Ticket():
        def __init__(self, weekend=False, child=False):
                self.exp = 100
                if weekend:
                        self.inc = 1.2
                else:
                        self.inc = 1
                if child:
                        self.discount = 0.5
                else:
                        self.discount = 1
        def calcPrice(self, num):
                return self.exp * self.inc * self.discount * num

>>> adult = Ticket()
>>> child = Ticket(child=True)
>>> print("2个成人 + 1个小孩平日票价为:%.2f" % (adult.calcPrice(2) + child.calcPrice(1)))
2个成人 + 1个小孩平日票价为:250.00

1*. 游戏编程:按以下要求定义一个乌龟类和鱼类并尝试编写游戏。(初学者不一定可以完整实现,但请务必先自己动手,你会从中学习到很多知识的)

  • 假设游戏场景为范围(x, y)为0<=x<=10,0<=y<=10
  • 游戏生成1只乌龟和10条鱼
  • 它们的移动方向均随机
  • 乌龟的最大移动能力是2(Ta可以随机选择1还是2移动),鱼儿的最大移动能力是1
  • 当移动到场景边缘,自动向反方向移动
  • 乌龟初始化体力为100(上限)
  • 乌龟每移动一次,体力消耗1
  • 当乌龟和鱼坐标重叠,乌龟吃掉鱼,乌龟体力增加20
  • 鱼暂不计算体力
  • 当乌龟体力值为0(挂掉)或者鱼儿的数量为0游戏结束

答:代码如下:

import random as r    #引入模块random,使用as指定别名r

legal_x=[0,10]     
legal_y=[0,10]        #设置游戏场景范围

class Turtle:
    def __init__(self):
        self.power=100     #体力上限100
        #self.movement=0
        self.x=r.randint(legal_x[0],legal_x[1])
        self.y=r.randint(legal_y[0],legal_y[1])      #随机生成乌龟的初始坐标

    def move(self):
        #self.movement= int(input("请输入移动1还是2:"))
        #随机计算方向并移动到新位置(x,y)
        new_x=self.x+r.choice([1,2,-1,-2])
        new_y=self.y+r.choice([1,2,-1,-2])    
        # 检查移动后是否超过场景x轴边界
        if new_x<legal_x[0]:
            self.x=legal_x[0]-(new_x-legal_x[0])
        elif new_x>legal_x[1]:
            self.x=legal_x[1]-(new_x-legal_x[1])
        else:
            self.x=new_x
        # 检查移动后是否超过场景y轴边界
        if new_y<legal_y[0]:
            self.y=legal_y[0]-(new_y-legal_y[0])
        elif new_y>legal_y[1]:
            self.y=legal_y[1]-(new_y-legal_y[1])
        else:
            self.y=new_y
        #体力消耗1
        self.power-=1
        #返回移动后的新位置
        return (self.x,self.y)     

    def eatfish(self):
        print("乌龟和鱼坐标重叠,乌龟吃掉鱼!体力增加20")
        self.power+=20
        if self.power>100:
            self.power=100
        
class Fish:
    def __init__(self):
        #随机生成鱼的初始坐标
        self.x=r.randint(legal_x[0],legal_x[1])
        self.y=r.randint(legal_y[0],legal_y[1])

    def move(self):
        #随机计算方向并移动到新位置(x,y)
        new_x=self.x+r.choice([1,-1])
        new_y=self.y+r.choice([1,-1])    
        # 检查移动后是否超过场景x轴边界
        if new_x<legal_x[0]:
            self.x=legal_x[0]-(new_x-legal_x[0])
        elif new_x>legal_x[1]:
            self.x=legal_x[1]-(new_x-legal_x[1])
        else:
            self.x=new_x
        # 检查移动后是否超过场景y轴边界
        if new_y<legal_y[0]:
            self.y=legal_y[0]-(new_y-legal_y[0])
        elif new_y>legal_y[1]:
            self.y=legal_y[1]-(new_y-legal_y[1])
        else:
            self.y=new_y
        #返回移动后的新位置
        return (self.x,self.y)

turtle=Turtle()
fish=[]
for i in range(10):
    new_fish=Fish()
    fish.append(new_fish)

while True:
    if not len(fish):
        print("鱼儿都吃完了。游戏结束!")
        break
    if not turtle.power:
        print("乌龟体力耗尽,游戏结束!")
        break

    pos=turtle.move()
    
    # 在迭代器中删除列表元素是非常危险的,经常会出现意想不到的问题,因为迭代器是直接引用列表的数据进行引用
    # 这里我们把列表拷贝给迭代器,然后对原列表进行删除操作就不会有问题了^_^
    for each_fish in fish[:]:
        if each_fish.move==pos:
            turtle.eat
            fish.remove(each_fish)
            print("有一条鱼儿被吃掉了...")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早知晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值