【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)
原文地址:https://www.cnblogs.com/python-test001/p/12397693.html