python基础篇{面向对象}

 python基础学习路线:

   · 数据分析之python基础篇{基础语法}
   · 数据分析之python基础篇{数据类型}
   · 数据分析之python基础篇{控制流语句}
   · 数据分析之python基础篇{函数}
   · 数据分析之python基础篇{模块}
   · 数据分析之python基础篇{文件操作}
   · 数据分析之python基础篇{Pymysql}
   · 数据分析之python基础篇{面向对象}

概念理解

  就目前来说,程序员们有两种代码思维:面向过程和面向对象

面向过程

  从字面上理解,我们不难理解,面向过程其实就是针对问题的解决步骤来实现代码逻辑。我们把最终的代码实现结果想象成一个问题的解,我们要去解决一个问题,我们会将这个问题拆分成一个一个的过程,然后依次执行。

  比如说:吃饺子这个问题,我们可以这个问题划分成以下6步进行。

  1. 菜市场买材料
  2. 洗菜,切菜,剁馅
  3. 和面,擀皮
  4. 包饺子
  5. 煮饺子
  6. 吃饺子

面向对象

  那么我们从字面上理解,对象就是某一种事物,那么面向对象的思维,就是说我们直接跳过过程,跳过解决问题的每一个步骤,直接针对可以解决问题的事物,所以说,对象必须要有可以解决问题的能力。

  比如说,我们有一个定义了对象,我们把可以让大家吃上饺子的一系列技能赋予给这个对象。然后

  • 对象具有了买菜技能,切菜技能,包饺子技能,煮饺子技能.
  • 我想吃饺子了,对象给你做。你等着吃就行了

概念简述

面向过程

  面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。根据业务逻辑从上到下写代码。

 面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程的思路是将数据与函数按照执行的逻辑顺序组织在一起,数据与函数分开考虑。

  面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

  • 优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
  • 缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

面向对象

  面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程

  面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。

  面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。

  • 优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
  • 缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。

面向对象

面向对象的概念

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
    在这里插入图片描述

  • 方法:类中定义的函数。

  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

  • 实例化:创建一个类的实例,类的具体对象。

  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

  • 实例变量:定义在方法中的变量,只作用于当前实例的类。

  • 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。

  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

创建类

  使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:

class 类名称:
    类的属性
    类的方法.

 就比如说:

# 定义一个Human学员的类
# 习惯性: 类使用大写字母开头
class Human:
    """类功能: 用于记录所有CDA学员"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'

类的实例化

  类似于赋值变量的操作

# 实例化对象
a = Human() 
b = Human()
# 我们可以查看以下a的类型
type(a)


# 运行结果
__main__.Human

属性的引用

  类似于方法调用的操作

a.eyes_num
a.hair_color
b.eyes_num
b.hair_color

类属性的操作

  属性可以重新赋值

# 改变类的属性值 , 当改变类的属性值,所有对象都会同步改变
Human.eyes_num = 3
a.eyes_num # 返回值为3
b.eyes_num # 返回值为3

# 添加一个新的属性, 所有对象都会获得这个新的属性
# 通过类名.属性名 可以给类添加新的属性
Human.name = '张三'
# 每一个由该类别实例化的对象也会具有该属性
a.name # 返回值为张三
b.name # 返回值为张三
Human.city = "深圳"


# 我们给某个对象的属性重新赋值, 则改变这个对象的该属性值
a.name = '李四' 
a.name # 返回结果为李四
# 其他对象该属性不会发生变化
b.name # 返回结果仍然为张三

  类属性一般用来储存所有通过类实例化的对象共有的属性.,这里如果出现a和b的城市都是深圳, 是类共有的属性, 用类属性来保存是合理的.
  但两个学员姓名都是张三? 这明显是不合适的.

    那么我们如何更改让每个实例(对象)都有不同的变量值呢?

类的方法

 类似于自定义函数的操作

# 定义一个Human的类
class Human:
    """类功能: 用于记录Humand的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def listen_class(self): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        return '这个人在听课'
# 因为重新定义了类,所以要重新定义类的实例化对象
a = Human()
b = Human()

a.hair_color  # 返回值为 black
b.eyes_num  # 返回值为 2

# 方法必须加括号
a.listen_class() # 返回值为'这个人在听课'

  类的方法实际上就是封装在类中的函数, 类中的方法一定会具有一个参数, 这个参数就是该对象本身,

 我们这里以self来代表目前调用这个方法的对象.

  也就是说类的方法和函数的区别在于, 方法已经有了一个要操作的对象了, 而函数需要把操作的目标传入进去。

类的方法的参数

  和函数相同, 类也可以具有参数, 参数在调用方法的时候传入即可。

# 定义一个Human的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def listen_class(self): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        return '这个人在听课'
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)
        
# 因为重新定义了类,所以要重新定义类的实例化对象
a = Human()
b = Human()

a.listen_class() # 返回结果为'这个人在听课'


b.sing_a_song('春天里')  # 返回结果为'这个人正在唱歌, 歌曲的名字叫做:小燕子'

练习

  调用该方法时, 返回的位置是xxxx

# 定义一个CDA学员的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def listen_class(self): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        return '这个人在听课'
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)
    def return_location(self, location ):  
        return '这个人目前处于:'+location  # 字符串拼接

初始化方法

  在类被实例化的时候, 有一个方法会被自动运行, 这个方法就是 __init__(self)

  这个方法主要用于, 在一个对象被实例化的时候, 为它赋予一个属于自己的属性.

  例如, Human的姓名, 这个姓名我们不能用类属性进行保存, 因为每个学员的姓名是不同的,姓名不是共同属性啊

  这种针对于每个对象不同的变量我们叫做实例变量

# 初始化方法: 当一个对象被创建出来的时候,就会自动运行一次的方法
# 定义一个CDA学员的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age  
    
    def listen_class(self): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        return '这个人在听课'
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)
# 当实例化的时候, __init__ 这个特殊方法就会自动被运行
a = Human('令狐冲', 28)
b = Human('李寻欢', 42)
a.eyes_num # 共同属性
a.name # 返回的属性为令狐冲
b.name # 返回的属性为李寻欢

可以在方法中直接使用类属性和实例属性

# 初始化方法: 当一个对象被创建出来的时候,就会自动运行一次的方法
# 定义一个CDA学员的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age  
    
    def listen_class(self): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        return '这个人在听课'
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)

    def introduce(self):
        return "大家好,我叫做{},我今年{}岁,我有{}只眼睛,我的头发是{}色的.".format(self.name,self.age,self.eyes_num,self.hair_color)
    # 如果调用属性什么前缀都不加,默认使用的是全局变量
# 当实例化的时候, __init__ 这个特殊方法就会自动被运行
a = Human('令狐冲', 28) 
b = Human('李寻欢', 42)  
a.introduce()
# 返回结果是 '大家好,我叫做令狐冲,我今年28岁,我有2只眼睛,我的头发是black色的.'

b.introduce()
# 返回结果是 '大家好,我叫做李寻欢,我今年42岁,我有2只眼睛,我的头发是black色的.'

类的方法参数写法

# 初始化方法: 当一个对象被创建出来的时候,就会自动运行一次的方法
# 定义一个Human的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age  
    
    def listen_class(self , status): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        # 状态编码: 0 : 这个人没有听课  1: 这个人假装在听课  2: 这个人在认真听课
        if status == 0:
            return "{}没有在听课中".format(self.name)
        elif status == 1:
            return '{}在假装听课'.format(self.name)
        else:
            return '{}在认真听课'.format(self.name)
    
    
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)

    def introduce(self):
        return "大家好,我叫做{},我今年{}岁,我有{}只眼睛,我的头发是{}色的.".format(self.name,
                                            self.age,self.eyes_num,self.hair_color)
    # 如果调用属性什么前缀都不加,默认使用的是全局变量

# 当实例化的时候, __init__ 这个特殊方法就会自动被运行
a = Human('令狐冲', 28)
b = Human('李寻欢', 42)

a.listen_class(0)
# 返回结果:'令狐冲没有在听课中'

b.listen_class(1)
# 返回结果:'李寻欢在假装听课'

也可以在类创建之后再添加方法和属性

# 定义一个Human的类
class Human:
    """类功能: 用于记录Human的信息"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age  
    
    def listen_class(self , status): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        # 状态编码: 0 : 这个人没有听课  1: 这个人假装在听课  2: 这个人在认真听课
        if status == 0:
            return "{}没有在听课中".format(self.name)
        elif status == 1:
            return '{}在假装听课'.format(self.name)
        else:
            return '{}在认真听课'.format(self.name)
    
    
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)

    def introduce(self):
        return "大家好,我叫做{},我今年{}岁,我有{}只眼睛,我的头发是{}色的.".format(self.name,
                                            self.age,self.eyes_num,self.hair_color)
    # 如果调用属性什么前缀都不加,默认使用的是全局变量
a = Human('令狐冲', 22)
b = Human('李寻欢', 33)

# 我发现这个类的动作不太够,我想要一个新的跳高的动作
# 定义这个函数
def jump(self):
    return self.name+'正在跳高' # 到这里只是一个普通的函数
# 把函数传输到类里面去
Human.jump = jump

# 原来用这个类实例化出来的对象,也都具有了这个技能
a.jump()
# 返回结果:'令狐冲正在跳高'

b.jump()   
# 返回结果:'李寻欢正在跳高'

#直接传输新的类属性
Human.ear_nums = 2 # 新增类属性
a.ear_nums
# 返回结果为 2

# 可以给对象传输新的属性
a.武功 = '独孤九剑'
a.武功
# 返回结果:独孤九剑
b.武功 = '小李飞刀'
b.武功
# 返回结果:小李飞刀-

类属性可以用对象属性进行覆盖

# 类属性可以用对象属性进行覆盖
a.hair_color = 'yellow'
a.hair_color
# 返回结果:yellow
b.hair_color
# 返回结果:black
Human.hair_color
# 返回结果:black

小练习

class Human:
    place = "深圳" # 所有的实例都有这个共同的属性
    def __init__(self, name, age):# 这个name什么时候传呢? 实例化对象的时候传
        self.name = name
        self.age = age
    def listen_class(self, status):
        '''参数为学员的状态, status 为0 代表, 没有听课, 1代表正在听课, 2代表假装听课'''
        if status == 0:
            return '{}没有在听课'.format(self.name)
        elif status == 1:
            return '{}正在认真听课'.format(self.name)
        elif status == 2:
            return '{}假装在听课'.format(self.name)
    def song(self, song_name):
        return "这个人正在唱一首歌, 歌的名字叫做<{}>".format(song_name)
    def introduce(self):
        return "大家好, 我的名字是{}, 我今年{}岁, 我来自{}".format(self.name, self.age, self.place)
    def sleep(self, status):
        if status == 'yes':
            return "{}正在睡觉".format(self.name)
        elif status == 'no':
            return "{}很清醒".format(self.name)
        else:
            return "{}正在半梦半醒之中".format(self.name)
a = Human('令狐冲', 22)
b = Human('李寻欢', 33)
a.sleep('half')
# 返回结果:'令狐冲正在半梦半醒之中'

b.sleep('no')
# 返回结果:'李寻欢很清醒'

练习

  练习一:

  • 定义一个计算器Calculator的类
  • 类属性: 产地(Place_of_Origin) = ‘made in China’
  • 实例属性: 颜色(colour)品牌(brand)价格(price)
  • 方法(技能): sum(a, b)求两个数的和
    summ(a, b, c, d,…)求一系列数的和
    summ1(a, b, c, d,…)求一系列数的倒数和
  • 额外添加一个方法: 计算器自我介绍功能: 介绍自己的产地,价格,品牌,颜色

  最后实例化三个对象出来试试功能

class Calculator:
    # 类属性
    Place_of_Origin = 'made in China'
    # 实例化对象
    def __init__(self, color,brand , price):
        self.color = color
        self.brand = brand
        self.price = price
    # 方法 
    def sum(self,a,b):
        return a + b
    def summ(self, *args):
        n = 0# 累加器
        for i in args:
            n+=i
        return n
    
    def summ1(self,*args): # 传输进来自动打包成一个元组
        n = 0
        for i in args:
            n += 1/i
        return n
    def introduce(self):
        # 如果在不允许换行的地方换行, 需要加 \
        return '我是一个可爱的{}的计算器,我是被{}创造出来的,\
你只需要花{}钱就可以获得我,我的产地是{}'.format(self.color,
                                self.brand,self.price,self.Place_of_Origin )
# 实例化对象                                
a1 = Calculator('蓝色','晨光',32)
a2 = Calculator('黑色','宜家',43)
a1.introduce()
# 返回结果:'我是一个可爱的蓝色的计算器,我是被晨光创造出来的,你只需要花32钱就可以获得我,我的产地是made in China'
a2.introduce()
# 返回结果:'我是一个可爱的黑色的计算器,我是被宜家创造出来的,你只需要花43钱就可以获得我,我的产地是made in China'
a1.sum(4,3)
# 返回结果:7
a1.summ(3,2,1,2,3)
# 返回结果:7
a1.summ1(4,3,2,1)
# 返回结果:2.083333333333333

  练习二:在上面的类中给计算器添加一个减法功能

def minus(self,a,b):
    return a - b
# 将功能传递进类
Calculator.minus = minus
a1.minus(6,2)
# 返回结果:4

实例之间的交互

# 初始化方法: 当一个对象被创建出来的时候,就会自动运行一次的方法
class Human:
    """类功能: 用于记录Human"""
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    
    feeling = '正常'# 感觉的类属性
    
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age  
    
    def listen_class(self , status): # 在函数里面定义的方法,都有一个默认的参数 self
        # self 指代的是我们将来要用这个类实例化的想象
        # 状态编码: 0 : 这个人没有听课  1: 这个人假装在听课  2: 这个人在认真听课
        if status == 0:
            return "{}没有在听课中".format(self.name)
        elif status == 1:
            return '{}在假装听课'.format(self.name)
        else:
            return '{}在认真听课'.format(self.name)
    def sing_a_song(self , song_name):
        return '这个人正在唱歌, 歌曲的名字叫做:{}'.format(song_name)

    def introduce(self):
        return "大家好,我叫做{},我今年{}岁,我有{}只眼睛,我的头发是{}色的.".format(self.name,
                                            self.age,self.eyes_num,self.hair_color)
    # 如果调用属性什么前缀都不加,默认使用的是全局变量

# 开始实现 实例化对象之间的交互
    def hit(self,another_student): # 攻击:一定要有一个攻击的对象, another_student是形参,作为将会攻击的对象
        another_student.feeling = '疼痛'
        another_student.thinking = '愤怒' 
        # 可以发现的是 Human类并没有 think属性,在方法中,参数就是实例化的对象,所以实例化对象会自动添加属性。
        return self.name + "攻击了" + another_student.name
c1 = Human('令狐冲',32)
c2 = Human('岳不群',54)
c2.feeling
# 返回结果:正常
c1.feeling
# 返回结果:正常

#  如果此时调用c2.think,程序会报错,因为这个属性不是类的原有属性,它需要在对象产生后,才会产生
c2.hit(c1)
# 返回结果:'岳不群攻击了令狐冲'
c1.feeling
# 返回结果:疼痛
c1.thinking
# 返回结果:愤怒
c1.hit(c2)
# 返回结果:'令狐冲攻击了岳不群'
c2.feeling
# 返回结果:疼痛
c2.thinking
# 返回结果:愤怒
# 初始化方法: 当一个对象被创建出来的时候,就会自动运行一次的方法

class Human:
    # 类属性: 将来用这个类实例化出的所有对象,都有的属性
    eyes_num = 2 # 所有用这个类实例化的对象一定都有2只眼睛
    hair_color  = 'black'
    
    feeling = '正常'# 感觉的类属性
    
    # 给这个类添加功能, 学名: 叫做方法  method,(类里面定义的函数)
    def __init__(self, name, age, jineng): # 参数,传入这个对象的对象属性
        # 把传进来的参数, 赋值给这个对象
        self.name = name
        self.age = age 
        self.jineng = jineng
        
    def hit(self,another_student): # 攻击:一定要有一个攻击的对象, another_student将会攻击的对象
        another_student.feeling = '疼痛'
        another_student.thinking = '愤怒'
        if another_student.jineng == '独孤九剑':
            another_student.feeling = '正常'
            another_student.fantan(self)
        
        return self.name + "攻击了" + another_student.name
    
    def fantan(self, fantan_student):
        fantan_student.feeling = '流血'
        fantan_student.thinking = '委屈'
        print( '触发了反弹')

# c2 调用 hit 方法 ,因此 self 代表 c2
# 在 c2 的hit方法中, 触发了 c1 的fantan方法, self 为 c1 传入进去了, 因此 c1 在 c2 的 fantan方法中。

c2.hit(c1)
# 运行结果:触发了反弹
#           '岳不群攻击了令狐冲'
c1.feeling
# 运行结果:正常
c2.feeling
# 运行结果:流血
c2.thinking
# 运行结果:委屈

继承

继承与抽象

  先抽象再继承

  • 抽象即抽取类似或者说比较像的部分。比如说:

在这里插入图片描述

抽象分成两个层次:

  1. 将奥巴马和梅西这俩对象比较像的部分抽取成类
  2. 将人,猪,狗这三个类比较像的部分抽取成父类。

 抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)

  • 继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
    在这里插入图片描述

 抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

Python中继承的基本语法

class 类名(父类):
    类里面的代码
class GoodHuman:
    place = "深圳" # 所有的实例都有这个共同的属性
    feeling = '正常'
    
    def __init__(self, name, age):# 这个name什么时候传呢? 实例化对象的时候传
        self.name = name
        self.age = age
    def listen_class(self, status):
        '''参数为学员的状态, status 为0 代表, 没有听课, 1代表正在听课, 2代表假装听课'''
        if status == 0:
            return '{}没有在听课'.format(self.name)
        elif status == 1:
            return '{}正在认真听课'.format(self.name)
        elif status == 2:
            return '{}假装在听课'.format(self.name)
    def song(self, song_name):
        return "这个人正在唱一首歌, 歌的名字叫做<{}>".format(song_name)
    def introduce(self):
        return "大家好, 我的名字是{}, 我今年{}岁, 我来自{}".format(self.name, self.age, self.place)
    def sleep(self, status):
        if status == 'yes':
            return "{}正在睡觉".format(self.name)
        elif status == 'no':
            return "{}很清醒".format(self.name)
        else:
            return "{}正在半梦半醒之中".format(self.name)
    def hit(self, one_student):

        # 假如在攻击别人的时候, 会触发对方的反弹能力
        one_student.fantan(self)
        return "{}成功攻击了{}".format(self.name,  one_student.name)
    def fantan(self , other_student):
        self.feeling = '疼痛'
        self.thinking = '怒火'
        self.status = '防御'
        
        other_student.feeling = '疼痛'
        print( "{}发起了反击".format(self.name))
class BadHuman:
    '''说明:这是一个用于记录CDA学员的类
    参数说明:目前还没有参数'''
    place = "北京" # 所有的实例都有这个共同的属性
    feeling = '正常'
    
    def __init__(self, name, age):# 这个name什么时候传呢? 实例化对象的时候传
        self.name = name
        self.age = age
    def teacher_class(self, status):
        '''参数为学员的状态, status 为3 代表都在听课, 4代表有人在听课 , 5代表都没有在听课'''
        if status == 3:
            return '{}上课中,大家都在听课'.format(self.name)
        elif status == 4:
            return "{}上课中, 有一部分人在听课".format(self.name)
        elif status == 5:
            return '{}上课中, 没有人在听课'.format(self.name)
    def song(self, song_name):
        return "这个人正在唱一首歌, 歌的名字叫做<{}>".format(song_name)
    def introduce(self):
        return "大家好, 我的名字是{}, 我今年{}岁, 我来自{}".format(self.name, self.age, self.place)

    def hit(self, one_student):
        one_student.feeling = '严重受伤'
        one_student.thinking = "胆怯"
        self.thinking = '怒火中...'

  上面的两个类中, 有一部分功能是相同的

 居然要把相同的功能写两遍, 换你你能忍吗? 不能忍, 那么怎么办呢? 用继承

## 建立了父类
class AllHuman:
    """上面两个类中共同的部分,放入到这个父类当中"""
    place = "北京" # 所有的实例都有这个共同的属性
    feeling = '正常'
    def __init__(self, name, age):# 这个name什么时候传呢? 实例化对象的时候传
        self.name = name
        self.age = age
    def song(self, song_name):
        return "这个人正在唱一首歌, 歌的名字叫做<{}>".format(song_name)
    def introduce(self):
        return "大家好, 我的名字是{}, 我今年{}岁, 我来自{}".format(self.name, self.age, self.place)

# GoodHuman继承父类AllHuman
class GoodHuman(AllHuman):
    # 我想给他添加一些新功能
    def listen_class(self, status):
        '''参数为学员的状态, status 为0 代表, 没有听课, 1代表正在听课, 2代表假装听课'''
        if status == 0:
            return '{}没有在听课'.format(self.name)
        elif status == 1:
            return '{}正在认真听课'.format(self.name)
        elif status == 2:
            return '{}假装在听课'.format(self.name)
    def hit(self, one_student):

        # 假如在攻击别人的时候, 会触发对方的反弹能力
        one_student.fantan(self)
        return "{}成功攻击了{}".format(self.name,  one_student.name)
    def fantan(self , other_student):
        self.feeling = '疼痛'
        self.thinking = '怒火'
        self.status = '防御'
        
        other_student.feeling = '疼痛'
        print( "{}发起了反击".format(self.name))


# BadHuman继承父类AllHuman
class BadHuman(AllHuman):
    def teacher_class(self, status):
        '''参数为学员的状态, status 为3 代表都在听课, 4代表有人在听课 , 5代表都没有在听课'''
        if status == 3:
            return '{}上课中,大家都在听课'.format(self.name)
        elif status == 4:
            return "{}上课中, 有一部分人在听课".format(self.name)
        elif status == 5:
            return '{}上课中, 没有人在听课'.format(self.name)
    def hit(self, one_student):
        one_student.feeling = '严重受伤'
        one_student.thinking = "胆怯"
        self.thinking = '怒火中...'

c1 = GoodHuman('张三',23)
c1.song('大家好') 
# 运行结果:'这个人正在唱一首歌, 歌的名字叫做<大家好>'
c1.introduce()
# 运行结果:'大家好, 我的名字是张三, 我今年23岁, 我来自北京'
c1.listen_class(0)
# 运行结果:'张三没有在听课'

 可以发现实例化对象c1可以调用父类AllHuman类的方法

方法重写

  如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,在子类里面如果有和父类名称相同的方法,那么子类的方法,会覆盖掉父类的方法,实例如下:
  我们注意到, 在GoodHuman类和BadHuman类中都有hit的功能, 只是他们的hit功能有所区别.我们可以将hit功能也放入到AllHuman类当中, 然后对于和该功能不相同子类, 去重写这个方法.

class AllHuman:
    place = "深圳" # 所有的实例都有这个共同的属性
    feeling = '正常'
    
    def __init__(self, name, age):# 这个name什么时候传呢? 实例化对象的时候传
        self.name = name
        self.age = age
    def song(self, song_name):
        return "这个人正在唱一首歌, 歌的名字叫做<{}>".format(song_name)
    def introduce(self):
        return "大家好, 我的名字是{}, 我今年{}岁, 我来自{}".format(self.name, self.age, self.place)
    def hit(self, one_student):

        # 假如在攻击别人的时候, 会触发对方的反弹能力
        one_student.fantan(self)
        return "{}成功攻击了{}".format(self.name,  one_student.name)



## GoodHuman继承父类AllHuman
class GoodHuman(AllHuman):
    def listen_class(self, status):
        '''参数为学员的状态, status 为0 代表, 没有听课, 1代表正在听课, 2代表假装听课'''
        if status == 0:
            return '{}没有在听课'.format(self.name)
        elif status == 1:
            return '{}正在认真听课'.format(self.name)
        elif status == 2:
            return '{}假装在听课'.format(self.name)
        
    def sleep(self, status):
        if status == 'yes':
            return "{}正在睡觉".format(self.name)
        elif status == 'no':
            return "{}很清醒".format(self.name)
        else:
            return "{}正在半梦半醒之中".format(self.name)
    
    def fantan(self , other_student):
        self.feeling = '疼痛'
        self.thinking = '怒火'
        self.status = '防御'
        AllHuman
        other_student.feeling = '疼痛'
        print( "{}发起了反击".format(self.name))


# BadHuman继承父类AllHuman
        
class BadHuman(AllHuman):

    def teacher_class(self, status):
        '''参数为学员的状态, status 为3 代表都在听课, 4代表有人在听课 , 5代表都没有在听课'''
        if status == 3:
            return '{}上课中,大家都在听课'.format(self.name)
        elif status == 4:
            return "{}上课中, 有一部分人在听课".format(self.name)
        elif status == 5:
            return '{}上课中, 没有人在听课'.format(self.name)

    def hit(self, one_student):
        one_student.feeling = '严重受伤'
        one_student.thinking = "胆怯"
        self.thinking = '怒火中...'

大练习

 mysql数据库的操作非常复杂,不易于使用。

 设计一个Mysql数据库操作的类, 可以帮我们实现数据库操作的各种功能, 增删改查。

 我们直接用这个类,就可以方便的实现, 各种对数据库的操作。

实现建立数据库和建立表功能

# 连接数据库的功能
# 连接数据库的功能
class MysqlOperating:
    # 初始化方法,当对象被实例化的时候, 就自动建立好和数据库的连接了
    def __init__(self,host,user,password,database,charset,port= 3306):
        import pymysql
        self.connect = pymysql.connect( host = host,
                         port=port,
                         user = user,
                         password= password,
                         database = database,
                         charset = charset )
        # 光标也直接构建好
        self.cursor = self.connect.cursor()
        print(self.cursor)
    def create(self,table,*args):
        """创建表格功能
        table:表名
        *args: 每一个建立的字段及数据类型"""
        columns = ','.join(args)
        sql = "create table {} ({})".format(table,columns)
        print(sql)
        self.cursor.execute(sql)
        return '创建'+table +'成功'
    
          

  测试以下结果

mysql = MysqlOperating( host = '127.0.0.1', # 换成你自己的IP
                      user='root',
                      password='123456',
                      database = 'pysqlname',
                      charset='utf8',
                      port = 3306)
mysql.create('Student','id varchar(10)','name nvarchar(10)',
            'age int','sex nvarchar(10)')

  实现插入功能

class MysqlOperatingV2(MysqlOperating):# 集成上一个版本的功能
    # 写一个插入功能
    def insert(self , table, data ):
        """插入数据
        table: 表名
        data: 数据二维表格式"""
        # %s 的个数有data里面有几列决定的
        n = len(data[0])
        s = ','.join(["%s" for i in range(n)])
        self.cursor.executemany("""insert into {} values({})""".format(table,s),data)
        # 提交
        self.connect.commit()

  测试以下结果

data = [['001','何炅','50','男'],
        ['002','撒贝宁','44','男'],
        ['003','王鸥','36','女'],
        ['004','鬼鬼','31','女'],
       ]
# 要重新实例化对象
mysql = MysqlOperatingV2( host = '127.0.0.1', # 换成你自己的IP
                      user='root',
                      password='123456',
                      database = 'pysqlname',
                      charset='utf8',
                      port = 3306)
mysql.insert('Student',data)

继续完善MysqlOperating类的功能

class MysqlOperating:
    # 初始化方法,当对象被实例化的时候, 就自动建立好和数据库的连接了
    def __init__(self,host,user,password,database,charset,port= 3306):
        import pymysql
        self.connect = pymysql.connect( host = host,
                         port=port,
                         user = user,
                         password= password,
                         database = database,
                         charset = charset )
        # 光标也直接构建好
        self.cursor = self.connect.cursor()
        print(self.cursor)
    def create(self,table,*args):
        """创建表格功能
        table:表名
        *args: 每一个建立的字段及数据类型"""
        columns = ','.join(args)
        sql = "create table {} ({})".format(table,columns)
        print(sql)
        self.cursor.execute(sql)
        return '创建'+table +'成功'
# 查询数据    
    def select(self,col,table,condition=None):
            sql = "select {} from {}".format(col,table)
            # 判断是否传入了查询条件
            if condition:
                # 在刚才的sql语法后面添加条件
                sql+=" where " + condition
            # 执行代码
            self.cursor.execute(sql)
            self.data = self.cursor.fetchall()
            return self.data
# 更新数据
    def update(self,table,key,value,condition=None ):
        sql = "update {} set {} = '{}' where {}".format(table,key,value,condition)
        self.cursor.execute(sql)
        self.connect.commit() # 提交
        return '更改成功'
# 删除数据    
    def delete(self, table ,condition=None):
        sql = "delete from "+table
        if condition:
            sql+= " where "+condition
        print(sql)
        self.cursor.execute(sql)
        self.connect.commit() # 提交

  写一个游戏类

class Game_role:
    # 添加一个类属性,记录英雄的存活状态,默认是活着、
    status ='live'
    def __init__(self,name,ad,hp,am):
        self.name = name
        self.ad = ad  # 攻击力
        self.hp = hp  # 血量
        self.am = am  # 护甲
    def attack(self,another_role):
        # 当一个英雄被攻击之前,先判断发起攻击的英雄和被攻击的英雄的状态,如果任意一个是死亡状态,则不进行游戏
        if another_role.status == "death" or self.status =  "death":
            return "该英雄已经死亡了,无法发起进攻"
        # 被攻击的英雄血量会减少
        # 三个: 提取本英雄攻击力,提取被攻击英雄护甲,提取被攻击英雄血量
        another_role.hp -= self.ad - another_role.am
        # 如果被攻击英雄的血量少于0,那么将他的状态改为死亡,
        if another_role.hp <= 0:
            another_role.status = 'death'
            return another_role+'已经死亡!'
            
        return "{}攻击了{},{}掉了{}血,还剩{}血".format(self.name,another_role.name,another_role.name,
                                                  self.ad - another_role.am,another_role.hp)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值