0
点赞
收藏
分享

微信扫一扫

面向对象程序设计

面向对象程序设计

注意:本章笔记代码模块中的__,部分场景由于显示问题,将双下划线连接在一起,实际上为双下划线(编译环境中显示样式:_ _)

  • 概念

    • 面向对象编程:定义类→实例化→执行动作
      • eg. 把水蜜桃装进冰箱(Hint:水蜜桃属于水果类)
      • 面向对象:定义类(水果)→实例化(水蜜桃)→执行动作(把水蜜桃放进冰箱)
      • 面向过程:打开冰箱(怎么打开)→装水蜜桃(怎么装)→关闭冰箱(怎么关闭)
      • 对比,处理新水果:西瓜
        • 面向对象:实例化新实例(西瓜)→执行动作
        • 面向过程:西瓜比水蜜桃大,思考怎么装进冰箱;西瓜太重,怎么顺手开冰箱
  • 类:

    • 定义

    • 实例化

      • () 不可少
# 定义方法:
class Classname:    # 定义规范,类名首字母大写
    pass
# ---------------------------------------------------------------------------------
# 实例化
example = Classname() # ()不可少
class Game:
    pass
wzry = Game()   # 类的实例化,游戏类:王者荣耀wzry
print(type(Game))    # 表示Game的类型为class
print(type(wzry))    # 表示wzry的类型是当前程序的Game类的实例

  •  补充知识:

    • 对象三特征:value,id,type
    • 函数:面向过程
    • 方法:面向对象
      • 特例:类中的_ _init_ _为构造函数
    • 显示类包含的内容 : classname._ _dict_ _()
    • 构造函数:构造实例的进程函数
      • 语法 : def _ _init_ _(self):
      • self表示当前实例,不可缺少
      • 不能设置return值
      • class执行当前实例的函数
    • 方法:
      • 包含普通方法和类方法
      • 语法 : def methodname(self)
      • self表示当前实例
      • 任意返回值
      • 调用类中方法的语法 : Classname.methodname()
        • self不用输入参数
        • eg.
class Game:
    # self 表示类实例化后的当前实例
    def __init__(self):    # 建立实例构造函数
        pass
    # 不能设return值,否则报错
    def methodname(self):    # 定义普通方法,类方法下文会提到
        pass
    # 正常设置return值
  • 类属性:

    • classname._ _dict_ _ 显示类/
    • 类属性由类下所有实例共享
  •  实例仅访用类
    • 可以访问类属性,使用方法(含类方法),但数据不在实例dict里,默认为访问
    • 若实例无新定义类属性:
      • print自动打印类属性(默认设置为访问)
      • ._ _dict_ _显示实例无类属性
# 验证实例仅访用类
# 实例仅访用类定义:
# 实例可以访问类属性,使用方法(含类方法),但数据不在实例dict里,默认方式为访问
class Game:
    system = 'mobile game'  # 类属性:所有实例可以访问
    type = 'MOBA'   # 类属性:所有实例可以访问

wzry = Game()   # 类的实例化,游戏类:王者荣耀wzry
print(wzry.type)
print(Game.__dict__)
print('没有新定义实例属性后,实例的dict:')
print(wzry.__dict__)

jdqs = Game()
jdqs.type = 'FPS'
print('新定义实例属性后,实例的dict:')
print(jdqs.__dict__)
  • 输出结果:
    • 解释:
    • 第6行语句输出MOBA,表示实例的type属性可以访问类属性type(MOBA)
    • 第9行语句输出实例的dict显示为空,表示实例dict无类属性type
    • 第6、9行语句验证了实例仅访用类的概念
    • 第12行语句新定义实例的type属性
    • 第14行语句输出实例的dict显示含新定义的'FPS',表示实例dict有属性type='FPS'

  • 类方法:

    • 直接调用类属性
    • 类方法示例:
class Game:
    classgametype = 'FPS'
    def __init__(self,formgametype): #设置外部数据传入实例属性的入口,形参formgametype
        self.gametype = formgametype #设置实例的一个属性gametype,并传入外部数据
    def Gametype(self): #打印实例属性定义的gametype的方法
        print('实例属性定义的游戏类型是:', self.gametype)
# 类方法语句模块------------------------------------------------------------------------
    @classmethod   # 类方法声明,声明这个方法是类方法   
    def Gametypeclass(cls): 
    #打印类属性定义的gametype的方法 #方法变量名为当前通用标识符为cls,此处可替换为类名Game   
        print('类属性定义的游戏类型是:', cls.classgametype) 
        #调用当前类属性classgametype #语法:通用标识符cls.类属性名,此处可替换为Game.
# ---------------------------------------------------------------------------------
wzry = Game('MOBA')    # 外部数据通过形参导入实例属性
wzry.Gametype()    # 打印实例属性定义的Gametype
wzry.Gametypeclass()    # 打印类属性定义的Gametype

 

  •  类方法统计实例化个数,示例:
class Game:
    num = 0    # 计数记录
    def __init__(self,formgametype):#设置外部数据传入实例属性的入口,形参formgametype
        self.gametype = formgametype #设置实例的一个属性gametype,并传入外部数据
        Game.num += 1    # 每实例化一次后,num+1,可用_ _class_ _.num替换,方便修改
    @classmethod
    def numcount(cls):    # 注意括号内为cls,表示当前类
        print('一共实例化', cls.num, '个实例')    # 直接调用类属性
wzry = Game('MOBA')
jdqs = Game('FPS')
Game.numcount()    # 调用类Game中的方法numcount
# 输出结果:
# 一共实例化了2个实例

  •  构造函数

    • 基本知识

      • 构造实例的进程函数
      • 语法 : def _ _init_ _(self)
        • self表示当前实例,不可缺少
      • 不能设置return值
      • class执行当前实例的函数
    • 参数传递

      # self 表示当前实例!!!!!!!!
      class Game:
          gametype = 'FPS'   # 类属性,验证这个功能时可以略去
          systemtype = 'mobile game'  # 加入可观察验证仅访用机制
      # self 表示当前实例!!!!!!!!
          def __init__(self,sgametype,ssystem):   # 定义参数(外部数据)传入入口
              self.gametype = sgametype    # 设置实例的第一个属性gametype
              self.systemtype = ssystem    # 设置实例的第二个属性systemtype
      # self 表示当前实例!!!!!!!!
      wzry = Game('MOBA','PC')   # 实例化语句,传入参数(外部数据)给实例属性
      print(wzry.gametype, wzry.systemtype)    # 打印实例wzry的两个属性
      print(wzry.__dict__)    # 检验实例字典,结果说明参数成功传入实例,并保存在实例dict里

                

  • 构造函数内的参数调用

    • Y参数传入构造函数,其他方法也可以调用Y参数, 语法:self.parameter
    • eg.
class Game:
    def __init__(self, sgametype):  # 定义形参Y:sgametype
        self.gametype = sgametype
    def printgametype(self):
        print('这个游戏的类型是:', self.gametype)    # self.xxx调用Y参数
wzry = Game('MOBA')  # 实例化,并传入形参的内容
wzry.printgametype()    # 实例调用类方法

  • 静态方法

  • 访问权限控制

    • @property:将方法变成属性,访问方式改变,方法必须有返回值,因为是属性
      • 原,访问方式:class.method()
      • 使用@property后,访问方式:class.method
    • class内部私有方法:前置双下划线def _ _methodname(self)
      • 表示仅class内部可访问,class外不可访问,_ _表示隐藏符号
      • 用_ _后,class内部调用标识符为._ _parameter,不是.parameter
    • class内部私有变量:前置双下划线self._ _parameter
# 无限制访问
class School:
    area = 'China'
    def __init__(self,formpnum):
        self.pnum = formpnum
HKU = School(1000)
print(HKU.pnum)
# 打印得到 1000
# --------------------------------------------------------------------------------
# _ _设置class内部访问权限后
class School:
    area = 'China'
    def __init__(self,pnum):
        self.__pnum = pnum    # 限制class内部访问权限
HKU = School(1000)
print(HKU.__pnum)    
# 打印得到:
# AttributeError: 'School' object has no attribute 'pnum'
# 属性错误:'School'对象没有'pnum'属性
# --------------------------------------------------------------------------------
class School:
    area = 'China'
    def __init__(self,pnum):
        self.__pnum = pnum    # 限制class内部访问权限
# 以下语句涉及的过程有:建立打印私有变量 self.__pnum的解决办法,将方法变为类属性的过程
    @property
    def getpnum(self):
        return self.__pnum
HKU = School(1000)
print(HKU.getpnum)
# 打印得到 1000
  • 父子类:

    • 概念

      • 继承:下级有上级的所有功能,并且可以有新的功能
      • 父类
      • 子类(继承父类属性+行为,同时有自己属性/行为/属性+行为)
      • 抽象类比:
        • 父类:属性:西瓜;行为:解渴
        • 父类的继承子类A:属性:有籽,西瓜;行为:解渴
        • 父类的继承子类B:属性:无籽,西瓜;行为:解渴
    • 子类继承父类

      • 语法:四步走
      • 子类名后添加父类名+括号
        • class Student(Human):
      • 子类实例属性添加父类实例属性变量
        • def __init__(self, weight, height, hobby):
      • 子类构造函数内添加继承语句,并且键入父类实例属性变量(weight,height)
        • super().__init__(weight, height)
      • 实例化赋予父类实例属性(63,178)+子类实例属性('basketball')
        • A = Student(63,178,'basketball')
      • 若在第三步中,提前赋予父类实例属性,则第四步只要赋予子类实例属性(后续代码有演示)
# 语法实例
# 区分:父类实例、子类实例、类属性、实例属性、父类实例属性、子类实例属性
# self:当前实例,__init__(self,parameters)中的parameters为实例属性
# 定义父类
class Human:
    goal = 'love and peace'
    def __init__(self, weight, height):
        self.weight = weight
        self.height = height
    def Run(self):
        print(self.height, '在跑步')
# -----------------------------------------------------------------------
# 定义继承父类的子类
class Student(Human):    # 添加括号加父类名字(fathername)
    def __init__(self, weight, height, hobby):
        self.hobby = hobby
        super().__init__(weight, height) # 子类继承父类的实例属性(weight、height)、父类方法
        print('继承的父类-类属性为', self.goal)     # 子类实例可以访问父类的类属性
        print(self.__dict__)    # 检验是否存入子类实例dict中
        self.Run()    # 子类实例使用父类方法
# 17、18、19行结果表明父子类继承中——子类实例遵循'仅仿用'父类机制,不计入dict
# 个人理解:因为子类实例继承父类实例,而父类实例 '仅仿用' 父类,
# 所以子类实例'仅仿用' 父类
A = Student(63,178,'basketball')    # 子类实例需要输入父2+子1个属性值
# 若将 17 行改为:super().__init__(63, 178)
# 则 24 行随之更改为:A = Student('basketball')
# 上述为继承时,同时键入原理
# 输出内容为:

  • 方法重写

    • 继承父类的子类下,重写方法原则:子类方法名、方法变量名与父类相同
举报

相关推荐

0 条评论