【菜gou的CS61A学习笔记12 Class & Inheritance】

【菜gou的CS61A学习笔记12 Class & Inheritance】,第1张

        这两次课程主要介绍了python中的面向对象的设计思想,讲解了自定义类的写法和继承,个人认为是非常重要的,因为python也可以面向对象编程,所以重要的是掌握这种设计思想。如果是之前已经接触过C++或者Java,那么其实面向对象的思想都是通的,只需要有针对性的了解一下python的相关语法即可。

课程ppt如下:

Objects + Classes:https://inst.eecs.berkeley.edu/~cs61a/sp21/assets/slides/16-Objects_+_Classes_full.pdf

Inheritance + Composition:

https://inst.eecs.berkeley.edu/~cs61a/sp21/assets/slides/18-Special_Object_Methods_full.pdf 

 

一、lecture 1.1        Object and Class

        想象一下我们生活中的一些例子,比如我们小时后经常看的奥特曼吧,如果我们想用程序来记录一下各种奥特曼的属性、必杀(动作)还有怪兽的一些属性和必杀,我们该用什么样的方式来完成呢?如果使用简单的数据结构,比如列表或者字典,那么我们只能简单记录一些属性值;或者是使用数据结构+函数式编程的思想,我觉得这样也会让程序看起来比较乱,使代码的可读性降低。这时我们可以想到,可以把事物抽象成类!

        那么什么是类(class)呢?

        a. A class is a template for defining new data types.

        b. An instance of a class is called an object. (object可以类比为各种各样的奥特曼如艾斯、七爷等等)

        c. Each object has data attributes called instance variables that describe its state. Each object also has function attributes called methods. (这里就比如每个奥特曼有不同的属性和不同的必杀技)

        简答介绍完了什么是类,我们直接开门见山,直接开始介绍类的写法.

        

class Ultraman:
    # Set the initial values
    # Define methods
    def __init__(self, name, weight = 50, home = "M77"):
        self._name = name
        self._weight = weight
        self._home = home

    def Dazhao(self, SkillName):
        print(f"{self._name} 使出了 {SkillName} !")

        我们这里为了省事只是简单简单写了一个类,首先一个类是要有最开始的"构造函数",即__init__()函数,这个函数必须包含self参数 (The self in keyword in Python is used to all the instances in a class. By using the self keyword, one can easily access all the instances defined within a class, including its methods and attributes.). 然后就是包含一些初始化属性的变量,这里self._表示私有,体现了封装的思想. 同时,. Dot符号可以用来访问对象的属性和方法。我们接下来看一下用这个类创建一些简单的对象。

图1 : 简单的类对象展示 

         同时我们还可以在类内设置变量,简单看一下下面的例子:

图2: 类内变量展示         

        同时还有一个上文提到的重点,即__和_的联系,即这是封装的体现:

  • __ (double underscore) before very private attribute names
  • _ (single underscore) before semi-private attribute names
  • no underscore before public attribute names

1.2 Inheritance + Composition 

        这一节我们主要讲述一下继承,其实继承的目的就是为了减少代码的重复,我们直接以课上讲的例子展开,比如我们有一个动物保护区,需要构建各种动物的类, 我们首先构建一个兔子类和象类,代码如下:

class Rabbit:
    species_name = "European rabbit"
    scientific_name = "Oryctolagus cuniculus"
    calories_needed = 200

    def __init__(self, name, age=0):
        self.name = name
        self.age = age
        self.calories_eaten = 0
        self.happiness = 0

    def play(self, num_hours):
        self.happiness += (num_hours * 10)
        print("WHEEE PLAY TIME!")

    def eat(self, food):
        self.calories_eaten += food.calories
        print(f"Om nom nom yummy {food.name}")
        if self.calories_eaten > self.calories_needed:
            self.happiness -= 1
            print("Ugh so full")

    def interact_with(self, animal2):
        self.happiness += 4
        print(f"Yay happy fun time with {animal2.name}")


class Elephant:
    species_name = "African Savanna Elephant"
    scientific_name = "Loxodonta africana"
    calories_needed = 8000

    def __init__(self, name, age=0):
        self.name = name
        self.age = age
        self.calories_eaten  = 0
        self.happiness = 0

    def play(self, num_hours):
        self.happiness += (num_hours * 4)
        print("WHEEE PLAY TIME!")

    def eat(self, food):
        self.calories_eaten += food.calories
        print(f"Om nom nom yummy {food.name}")
        if self.calories_eaten > self.calories_needed:
            self.happiness -= 1
            print("Ugh so full")

    def interact_with(self, animal2):
        self.happiness += 1
        print(f"Yay happy fun time with {animal2.name}")

        可以发现,除了一些属性值有些差异,这两个类的方法其实差不太多,那么我们写多个这样的类不就是浪费时间了吗?基于此,我们提出了继承的方法,即创建一个父类,然后再对具体的类进行特殊的改动即可。

        

图3:继承说明 

         有了这种概念,那么我们就可以将上述的代码改动如下:

class Animal:
    species_name = "Animal"
    scientific_name = "Animalia"
    play_multiplier = 2
    interact_increment = 1

    def __init__(self, name, age=0):
        self.name = name
        self.age = age
        self.calories_eaten  = 0
        self.happiness = 0

    def play(self, num_hours):
        self.happiness += (num_hours * self.play_multiplier)
        print("WHEEE PLAY TIME!")

    def eat(self, food):
        self.calories_eaten += food.calories
        print(f"Om nom nom yummy {food.name}")
        if self.calories_eaten > self.calories_needed:
            self.happiness -= 1
            print("Ugh so full")

    def interact_with(self, animal2):
        self.happiness += self.interact_increment
        print(f"Yay happy fun time with {animal2.name}")


class Rabbit(Animal):
    species_name = "European rabbit"
    scientific_name = "Oryctolagus cuniculus"
    calories_needed = 200
    play_multiplier = 8
    interact_increment = 4
    num_in_litter = 12

class Elephant(Animal):
    species_name = "African Savanna Elephant"
    scientific_name = "Loxodonta africana"
    calories_needed = 8000
    play_multiplier = 4
    interact_increment = 2
    num_tusks = 2

        同时,我们还可以在子类内重写方法以完善子类的特殊作用以及可以使用super关键字来表示超类 。(super() is better style than BaseClassName, though slightly slower.)最后是多重继承也是可以的,只是本课内不涉及,有需要的可以参考一下其他资料。

        最后一个概念就是组合,即一个对象可以包含对其他类对象的引用。我们看一下下面的代码就可以理解:

class Rabbit(Animal):

    def reproduce_like_rabbits(self):
        if self.mate is None:
            print("oh no! better go on ZoOkCupid")
            return
        self.babies = []
        for _ in range(0, self.num_in_litter):
            self.babies.append(Rabbit("bunny", 0))

         简而言之,就是说一个对象可以在自身的属性方法中包含着若干其他对象的引用,这时python语法允许的,也是非常有用的一个点。

        最后是继承和组合的区别:

 图4: 继承和组合的区别

        以上就是这两次课的主要内容。本次笔记之后为了节约时间,我会简要的概括课上讲了什么,以便于自己复习使用,另外会加快更新本课程的lab和hw的内容,希望大家都有所收获,有所进步,谢谢 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/873577.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存