【python基础语法】继承、反射机制和面向对象编程(下)(第11天课堂笔记)
''' 继承: 1、类方法、静态方法、私有属性 类方法:使用装饰器@classmethod,第一个参数必须是当前类的对象,该参数名一般约定为"cls", 通过它来传递类的属性和方法(不能传实例的属性和方法),"cls"代表类本身 类方法调用:实例对象和类对象都可以调用 实例方法:只能由实例对象来调用 应用场景:需要站在类的角度执行某个行为时,那么就应该定义为类方法 静态方法(了解即可): 定义:使用装饰器@staticmethod,参数随意,没有"self"和"cls"参数, 但是方法体中不能使用类或者实例的任何属性和方法 调用:实例对象和类对象都可以调用 应用场景:存放逻辑代码,内部不需要引用类属性和实例属性 私有属性(了解即可): 单下划线开头:_attr 双下滑开头:__attr 声明为私有属性:声明为私有属性,那么该说明属性是类私有的,仅限于在类里面使用, 不要在类外面去调用(实际上类外面可以访问,讨论这个毫无意义) 2、类的继承关系 什么是继承,继承有什么作用? 面向对象编程中有一个重要的思想叫继承,子类通过继承可以获得父类的属性和方法, 被继承的类叫做父类(基类),继承的类叫子类 作用:子类通过继承可以获得父类的属性和方法,提高开发的效率及代码的复用率 类的两种定义方式: 方式一: class 类名: pass 方式二: class 类名(继承的父类): pass object:是所有类的顶级父类(基类) 类属性可以直接继承 实例方法通过继承可以得到 实例属性能不能继承? 实例属性是每个实例对象所独自有的,不是通过继承得到的 继承是针对类而言的,只有类里面的东西才能被继承 创建实例对象的时候才会进行赋值 将有限的时间和精力花在当前我们紧急要做的事情上面 在最短的时间用python去做自动化,而不是研究底层原理和高阶编程 3、重写父类方法 重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖父类中同名的方法 直接调用重写之后的方法,直接调用自身有的这个方法(不会去父类找) 在方法中调父类被重写的方法: 方式一:父类名.方法名 方式二:super().方法名() 扩展: ___new__方法:创建对象 Create and return a new object 面向对象的三大特征: 继承: 封装:将变量定为类属性和相似功能的函数(方法)进行封装 多态:鸭子类型 4、调用重名的父类方法 子类重写了父类的方法之后,如何在子类中再调用父类的方法? 方式一:父类.方法名(self) 方式二:super().方法名() 5、属性动态设置(反射机制) setattr:设置属性 getattr:获取属性 delattr:删除属性 总结: 万物皆对象 函数:函数对象 基本数据:str list 类:类对象 模块(文件):模块对象 包:包对象 自定义类创建出来的对象 ''' """ 特征(属性):血量(HP) 蓝量(XP) 攻击力(attack) 暴击率 行为(方法):技能1 技能2 技能3 移动 总结:类的定义、属性、方法,self的含义,初始化方法 问题需求: 需求V1:实现一个初始版的手机类(大哥大) 只能打电话 需求V2:实现一个定义功能机类 打电话、听音乐、发短信 需求V3:实现一个智能手机类 打电话、听音乐、发短信、看视频、玩游戏、手机支付、视频通话 """ class Hero: def __init__(self,name,HP): self.name = name self.HP = HP print("自动调用了---init---方法,完成实例对象的初始化") def move(self): print("走向战场") def skill(self): print("使用了技能砍一刀") class MyClass: # 定义类属性 attr = 100 # 私有属性(声明为私有属性之后,不要在类外面通过类或者对象去使用这个属性) _attr = 999 __attr = 99999 # 定义实例属性 def __init__(self,name,age): self.name = name self.age = age # 定义实例方法 def func1(self): print("实例方法1") # 定义类方法@classmethod @classmethod def c_func(cls): print("类方法c_func") # 静态方法,将函数定义到类里面来,可以定义为静态方法 @staticmethod def s_func(): print("这个是静态方法") # # 创建一个m对象,并给m对象赋值 m = MyClass("hc",18) # # 调用实例方法(类无法调用实例方法,例如:MyClass.func1()) # m.func1() # # # 对象调用类方法 m.c_func() # 类调用类方法 MyClass.c_func() # 静态方法的调用 MyClass.s_func() m.s_func() # 类的两种定义方式: # 如果不写继承的父类(默认也是继承于object) class Myclass: pass # 可以自己指定继承的父类 class MyClassA(object): pass # 继承关系,举例 class BasePhone(object): """大哥大""" # basephone手机的类属性 attr = "红色" # 定义实例属性,是独有的,需要传参数 def __init__(self,name): self.name = name # 定义实例方法,不是独有的,无需传参 def call_phone(self): print("打语音电话base") # Phone_V1继承BasePhone所有功能 class Phone_V1(BasePhone): # 功能机 def call_phone(self): print("打语音电话v1") def send_msg(self): print("发短信功能") def music(self): print("听音乐") class Phone_v2(Phone_V1): """智能机""" # 重写父类的方法,更新和升级父类方法 # 父类有一个方法,继承之后定义了一个和父类方法名相同的方法 def call_phone(self): print("拨打视频电话") print("时间过去了5分钟再转成语音通话") # 在方法中调用父类被重写的方法 # 方式一:类名.方法名(self) # 通过类调用实例方法,self必须自己传参 BasePhone.call_phone(self) # 方式二:super().方法名() super().call_phone() def game(self): print("玩游戏") def qq(self): print("聊QQ") xm = Phone_v2("华为P30") # 访问继承的实例方法 xm.call_phone() xm.send_msg() xm.game() # 调用父类的实例属性 print(xm.name) # 访问继承的属性 print(Phone_v2.attr) b1 = BasePhone("大哥大") v1 = Phone_V1("oppo音乐手机") p1 = Phone_v2("华为P30") print(p1.name) print(b1.name) print(v1.name) # 重写父类的call_phone方法后子类调用父类的方法 v2 = Phone_v2("华为P30") # 直接调用重写之后的方法,直接调用自身有的这个方法(不会调用父类的方法) v2.call_phone() # 重写父类方法的应用场景 class Obj(object): # 重写new方法 # 第一种调用new方法的方式,自己创建的new方法无法创建对象,需要借用父类的 def __new__(cls,*arg,**kwargs): # object.__new__(cls) # 第二种: res = super().__new__(cls) return res # 通过类名创建对象,没有重写new方法,默认调用object类中的new方法 o = Obj() print(o) # 属性动态属性(反射机制): class Cases: def __init__(self,name): self.name = name case1 = Cases("111") datas = {"case_id":1,"data":"999","url":"www.baidu.com"} # 对象.属性名 = 属性值 # setattr:设置属性 # 给对象动态设置属性:参数(对象,属性名,属性值) setattr(case1,"age",99) # 等同于:case1.age = 99 print(case1.age) for k,v in datas.items(): print(k,v,type(k),type(v)) # case1.k = v setattr(case1,k,v) print(case1.url) # getattr:获取属性 res = getattr(case1,"name") print(res) # delattr:删除属性 res = delattr(case1,"name") print(res)