小甲鱼37课:类和对象,面对对象的编程总结反思

首先课上总结:(看了其他视频的一个总结:)
第一部分,基础认知:

class People:

People便是一个大类,且开头要用大写

class People:
    high =178
    def eat(self):

tom = People()
tom.eat()
gugu = People()
gugu.eat()

high叫属性,在这类人这个大类下全都178.
tom叫做类对象,也就是人这个大类下,一类叫tom的人,tom这个类对象的地址和self地址相同。因此self作用其实就是引用tom这个人的一切做法。也就是引用方法,也就是tom.eat(),其中.eat就是方法,针对tom这个类对象这类人会做的方法。tom.eat = self.eat。同样,gugu.eat是gugu在吃,此时self等于gugu,即gugu.eat = self.eat.
总之哪个对象(tom。gugu)调用那种方法(eat),self就是这种对象行为的引用。

所以课后题:
5.请解释下边代码错误的原因:

>>> class MyClass:
    name = 'Fishc'
    def myFun(self):
        print("Hello FishC!")

        
>>> MyClass.name
'Fishc'
>>> MyClass.myFun()
Traceback (most recent call last):
  File "", line 1, in <module>
    MyClass.myFun()
TypeError: myFun() missing 1 required positional argument: 'self'

可以看到。在类下直接找类的属性是没有任何问题的,因为属性代表的就是类这个大类的特征。
而后面在大类下看行为,也就是.myFun()。这就需要具体到一个对象来进行这个行为,因此必须先定义一个人比如tom = Myclass(),也就是这大类下tom这个人做.myFun这个事情。所以改写为:

class MyClass:
    name = 'Fishc'
    def myFun(self):
        print("Hello FishC!")
tom = MyClass()
tom.myFun()

第二部分:赋值属性

class People:
    def __init__(self,name1):
        self.name =name1
        #self.属性 = 形参
    def run (self):
        print("%s在奔跑!"% self.name)
tom = People("Tom")
tom.run()
gugu =People("GuGu")
gugu.run()

首先,创建类函数会有两个步骤:1.开辟空间2.初始化值,因此初始化函数——init——是在引用类时自动开始得一个函数,不需要刻意去引用它
接着,赋值方法有很多种。比如以上例子改为外部赋值:

class People:
    def run (self):
        print("%s在奔跑!"% self.name)
tom = People()
tom.name = "tom"
#在这儿进行对name属性的赋值
tom.run()

由于tom = self的地址,因此self.name =‘tom’
但是这种方法容易受顺序限制
于是便有:

class People:
    def __init__(self,name1):
        self.name ='Tom'
    def run (self):
        print("%s在奔跑!"% self.name)
tom = People()
tom.run()
gugu =People()
gugu.run()

这种方法会在初始化给self定一个属性那么叫tom,但是存在的问题是tom也会给gugu,这并不是想要的

于是__init__有(self,形参1,形参2)
所以此时 定义self.属性 = 形参,便如最开始的例子。
定义一个类对象tom = People()时候。就可以将形参写入,这样形参就会到self.属性,不同的形参就可以对应不同的值

PS:另外内置方法:
del:会在最后一个行为做完后,内存清空前运行输出:若为全局变量,则不论运行顺序

0.按照以下要求定义一个游乐园门票的类,并尝试计算2个成人+1个小孩平日票价。
平日票价100元
周末票价为平日的120%
儿童半票

class Ticket:
    def __init__(self,child=False,weekend=False):
        self.normal_price = 100
        #固定的价格,可以当做不变的属性写上
        if weekend:
            self.weekend_price = 1.2
        else:
            self.weekend_price = 1
        if child:
            self.child_price =0.5
        else:
             self.child_price =1

    def allprice(self,num):
        return  self.normal_price*self.weekend_price*self.child_price*num
        #所有折扣乘数量等于最终总价折扣在乘原价总价
        #学习这里利用初始化进行条件的判断,很实用
#非周末
human = Ticket()
Child = Ticket(child = True)
print('2大1小非周末价格为:%.2f'%(human.allprice(2)+Child.allprice(2)))
#周末
human = Ticket(weekend=True)
Child = Ticket(child = True,weekend=True)
print('2大1小周末价格为:%.2f'%(human.allprice(2)+Child.allprice(2)))

本题初始化值都没使用不固定的形参来对应价格,而是用来判断情况。而像一般价格这种固定值则可先写出来不论对象值都为100

1.游戏编程:按以下要求定义一个乌龟类和鱼类并尝试编写游戏。(初学者不一定可以完整实现,但请务必先自己动手,你会从中学到很多)
游戏场景为范围(x,y)为 0<=x<=10,0<=y<=10
游戏生成1只乌龟和10条鱼
它们的移动方向均随机
乌龟的最大移动能力为2(可以随机选择1还是2),鱼儿的最大移动能力为1
当移动到场景边缘,自动向反方向移动
乌龟初始化体力为100(上限)
乌龟每移动一次,体力消耗1
当乌龟和鱼坐标重叠,乌龟吃掉鱼,乌龟体力增加20
鱼暂不计算体力
当乌龟体力值为0(挂掉)或鱼儿的数量为0游戏结束

import random as r
class Turtle:
    def __init__(self):
        #初始化数据
        self.physical_strength = 100
        #初始位置随机
        self.x = r.randint(0,10)
        self.y = r.randint(0,10)
    def move(self):
        #移动多少(用new_x代替是为了后面的判断后在赋值)
        new_x = self.x + r.choice([-2,-1,1,2])#choice:随机返回元祖列表字符串任意元素
        new_y = self.y + r.choice([-2,-1,1,2])
        #判断是否出去
        if new_x<0:
            self.x = 0-(new_x)
        elif new_x >10:
            self.x = 20-(new_x)
        else:
            self.x = new_x
        if new_y<0:
            self.y = 0-(new_y)
        elif new_y >10:
            self.y = 20-(new_y)
        else:
            self.y = new_y
        # 体力消耗
        self.physical_strength -= 1
        # 返回移动后的新位置
        return (self.x, self.y)
        #可以当做元组返回哟!
    #加体力
    def eat(self):
        self.physical_strength += 20
        if self.physical_strength >= 100:
            self.physical_strength = 100
        

class Fish:
    def __init__(self):
        self.x = r.randint(0, 10)
        self.y = r.randint(0, 10)

    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 < 0:
            self.x = 0 - new_x
        elif new_x > 10:
            self.x = 10 - (new_x - 10)
        else:
            self.x = new_x
        # 检查移动后是否超出场景y轴边界
        if new_y < 0:
            self.y = 0 - new_y
        elif new_y > 10:
            self.y = 10 - (new_y - 10)
        else:
            self.y = new_y
        # 返回移动后的新位置
        return (self.x, self.y)
#测试
#注意开始时候是全部和类对其!
turtle = Turtle()
fish = []
    #用列表和for循环进行鱼增加操作,每1次就会有一组初始化数据保存进列表中
for i in range(10):
    new_fish = Fish()
    fish.append(new_fish)
#开始游戏不停
    while True:
#首先写停止游戏条件。鱼没了,龟死了
        if not len(fish):
            print('鱼没了,游戏结束!')
            break
        if not turtle.physical_strength:
            #注意,你调用的是一个变量,而不是函数,不要加括号!!!!!!!!
            print('龟死了,游戏结束!')
            break


    #游戏开始
        print('龟的坐标是:',(turtle.x,turtle.y))
    ***#坐标用文字+元祖的模式输出***
        turtle.move()
        print('龟现在的坐标是:',(turtle.x,turtle.y))
        for each in fish:
            #相当于each = Fish(),所以后面坐标全部用each.x
            #这就是在类里面用for循环的妙处,直接元素可以进去初始化得到一个初始化坐标数据,而且每次由于初始化里面ran函数会不一样
            print('鱼的坐标是:',(each.x,each.y))
            each.move()
            print('鱼现在的坐标是:',(each.x,each.y))
        
            if turtle.x == each.x and turtle.y == each.y:
                #不能直接比较元组,除非用cmp,不然会比较首个坐标,所以单个元素
                #用remove直接去元素比较好
                turtle.eat()
                fish.remove(each)
                print('死了一只小鱼,龟体力增加20')

1.一定注意调用变量无括号,调用函数有,for循环列表inlist不用加括号
2.self.xxx 是可以任意加减的,只要其值为int型
3.每个函数要么print,要么必须有个返回值,且返回值不能为等式,可以返回元祖内型,则为一个坐标等
4.在类里面用for循环的妙处,直接元素可以进去初始化得到一个初始化坐标数据,而且每次由于初始化里面ran函数会不一样
5.在一个游戏制作中。首先是对不同分类,且不同条件下的属性方法进行定义,然后开始对类进行变量赋值,注意此时与类的定义是在同列,不然不找不到类的定义,游戏开始后(whlie True),则先写游戏终止条件,在写游戏开始得顺序,这个逻辑比较好
6.字符串,元祖拼接是可行的

你可能感兴趣的:(小甲鱼37课:类和对象,面对对象的编程总结反思)