• python学习之路day07(类的继承和多态)



    1.###继承
    """
    (1)单继承
    至少2个类,子类 和父类
    一个类继承另外一个类,当前类是子类(衍生类)
    被继承的这个类是父类,(基类和超类)

    Python所有类的父类都是object
    """
    #1.子类继承后,子类可以使用父类的公有方法
    class Father():
    skin="黑色的"
    __sex="man"
    def hobby(self):
    print("爱好打篮球")
    def __smoke(self):
    print("爱好抽大麻")

    class Daughter(Father):
    pass

    obj=Daughter()
    print(obj.skin)
    obj.hobby()

    #2.子类继承后,子类不可以使用父类的私有方法
    class Son(Father):
    def pub_func(self):
    print(self.__sex)
    obj=Son()
    # print(obj.__sex) AttributeError
    # print(obj.__smoke) AttributeError
    print(obj.skin)
    # obj.pub_func() AttributeError
    #3.子父继承后,子类可以改写父类方法
    """self对象优先调用本类的方法,如果本类当中没有,再调用父类...."""
    class not_child(Father):
    skin = "白色的"
    def hobby(self):
    print("白种人喜欢种大麻")
    obj=not_child()
    print(obj.skin)

    2.####多继承
    # 1.基本语法
    class Father():
    f_property="英俊潇洒,才华横溢,道貌岸然,一表人才"
    def hobby(self):
    print("抽烟,喝酒,烫头,吃喝嫖赌")

    class Mother():
    m_property = "美丽大方,漂亮温柔"
    def hobby(self):
    print("麦包包,打麻将,蹦野迪")
    class Daughter(Father,Mother):
    pass

    obj=Daughter()
    print(obj.f_property)
    obj.hobby() #优先继承爸爸,所以继承爸爸的hobby

    # 2.self 和 super的区别
    """
    (1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
    (2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
    (3)super用途: 解决复杂的多继承调用顺序
    """
    class Father():
    f_property="英俊潇洒,才华横溢,道貌岸然,一表人才"
    def hobby1():
    print("抽烟,喝酒,烫头,吃喝嫖赌")

    class Mother():
    m_property = "美丽大方,漂亮温柔"
    def hobby2(self):
    print("麦包包,打麻将,蹦野迪")
    class Son(Father,Mother):
    m_property = "一枝梨花压海棠"
    def hobby2(self):
    print("出入奇怪的场所,比如卡丁车,蹦极")
    def skill1(self):
    print(Father.f_property)
    # self.hobby1() error
    Father.hobby1()
    """
    self 在调用成员的时候,如果自己本类有,优先调用自己的
    self 在调用成员的时候,如果自己本类无,调用父类的
    """
    def skill2(self):
    print(self.m_property)
    self.hobby2()

    """
    #super
    super在调用的时候,一定会优先调用父类的方法或者属性
    这是它与self的本质区别
    """

    def skill3(self):
    print(super().m_property)
    super().hobby2() #优先调用父类的
    obj=Son()
    obj.skill1()
    obj.skill2()
    obj.skill3()
    3.#菱形继承(钻石继承)
    """
    Human
    Man Woman
    Children
    """
    class Hunam():
    pty=1
    def feelT(self):
    print("古代人类,天冷了,穿动物的毛1")
    print(self.pty)
    print("古代人类,天热了,坑树皮2")
    class Man(Hunam):
    pty = 2
    def feelT(self):
    print("现代人类,天热了,喝啤酒,吃西瓜3")
    super().feelT()
    print("现代人类,天冷了,喝啤酒,吃火锅4")
    class Woman(Hunam):
    pty = 3
    def feelT(self):
    print("现代女性,天热了,穿裙子,光膀子,麦包包5")
    super().feelT()
    print("现代女性,天冷了,穿动物的毛,貂皮大衣6")
    class Children(Man,Woman):
    pty = 4
    def feelT(self):
    print("现代小孩,天热了,吃冰棍,游泳7")
    super().feelT()
    print("现代小孩,天冷了,喝热水,玩农药8")
    obj=Children()
    obj.feelT()

    """
    super 遵循mro列表中出现顺序,一次调用
    类.mro
    """
    lst=Children.mro()
    print(lst)
    """
    super 在调用同名方法时,要依据该列表中出现的类的调用顺序,依次调用
    [<class '__main__.Children'>, <class '__main__.Man'>, <class '__main__.Woman'>, <class '__main__.Hunam'>, <class 'object'>]
    """

    """
    现代小孩,天热了,吃冰棍,游泳7
    现代人类,天热了,喝啤酒,吃西瓜3
    现代女性,天热了,穿裙子,光膀子,麦包包5
    古代人类,天冷了,穿动物的毛1
    4
    古代人类,天热了,坑树皮2
    现代女性,天冷了,穿动物的毛,貂皮大衣6
    现代人类,天冷了,喝啤酒,吃火锅4
    现代小孩,天冷了,喝热水,玩农药8
    """
    4.# ###多态
    """
    不同的子类对象,调用相同的父类方法,产生不同的执行结果
    继承,重写
    好处:多态针对的是对象来说的,在不改变原有代码的前提下,完成不同的功能
    不同的对象,相同的方法,大道了不同的功能。
    """
    class Soldier():
    def attact(self):
    pass
    def back(self):
    pass

    class Army(Soldier):
    def attact(self):
    print("[陆军]拿一把枪,突突突,然后倒下!")
    def back(self):
    print("[陆军]撒腿就跑,躺下装死")

    class Navy(Soldier):
    def attact(self):
    print("[海军]开炮,鱼雷,拿鱼叉子插死敌人")
    def back(self):
    print("[海军]立即跳海,下海喂鱼!")

    class Airforce(Soldier):
    def attact(self):
    print("[空军]空对地导弹,使用二营长的意大利炮,射死敌人")
    def back(self):
    print("[空军]立即跳伞,落地成盒!")

    #实例化一个陆军士兵
    obj_army=Army()
    #实例化一个海军士兵
    obj_navy=Navy()
    #实例化一个空军士兵
    obj_airforce=Airforce()

    strvar="""
    1.全体出击。
    2.全体撤退。
    3.空军上,其他撤退。
    """

    lst=[obj_army,obj_navy,obj_airforce]
    while True:
    print(strvar)
    num = input("请发号施令>>>:")
    if num.isdecimal():
    if int(num)==1:
    for i in lst:
    i.attact()
    elif int(num)==2:
    for i in lst:
    i.back()
    elif int(num)==3:
    for i in lst:
    if isinstance(i,Airforce):
    i.attact()
    else:
    i.back()
    else:
    print("风太大,听不请.....")

    else:
    if num.upper()=="Q":
    print("指挥完毕,请下次再来!")
    5.###__new__魔术方法
    """
    触发时机:实例化类生成对象的时候触发(触发时机在__int__之前)
    功能:控制对象的创建过程
    参数:至少一个cls接受当前的类,其他根据情况决定
    返回值:通常返回对象或None
    """
    """
    对象.属性
    对象.方法()

    类.属性
    类.方法()

    object 是所有类的父类
    """
    #(1)基本语法
    class MyClass():
    a=5

    obj2=MyClass()
    print(obj2)
    class MyClass2():
    def __new__(cls):
    print(cls) #<class '__main__.MyClass2'>
    #通过父类object中的__new__魔术方法,返回该类的对象,参数是类
    # obj=object.__new__(cls)
    #返回本类对象,只能通过父类创建
    #return obj
    #可以返回None
    return obj2
    obj=MyClass2()
    print(obj) #<__main__.MyClass2 object at 0x000000000220FF60>
    print(obj.a) #5

    #对比__new__和__init__之间的区别
    """
    __new__ 负责创建对象
    __init__ 负责初始化对象
    __new__在__init__ 触发时机之前
    """
    #__new__和__init__形参实参要匹配
    class MyClass3():
    #用收集参数,一劳永逸
    def __new__(cls, *args, **kwargs):
    print(1)
    return object.__new__(cls)
    def __init__(self,name,age,sex):
    print(2)
    self.name=name
    self.age=age
    self.sex=sex
    obj=MyClass3("Alex",27,"未知")
    print(obj.name)
    print(obj.age)
    print(obj.sex)

    #(3)注意点:__init__只能初始化自己本类的对象
    class MyClass4():
    def __new__(cls, *args, **kwargs):
    print(1)
    return obj2
    #不会调用init方法,因为返回的不是没有class 本身的,不调用
    def __init__(self):
    print(2)
    obj=MyClass4()
    print(obj) #<__main__.MyClass object at 0x0000000001E7FFD0> 不会打印2

    6.###单态模式
    """
    类无论实例化多少次,都有且只有一个对象,
    """
    #1.基本语法
    class SingTon():
    # 防止类外调用__obj,形成封装保护.
    __obj = None
    def __new__(cls, *args, **kwargs):
    if cls.__obj is None:
    cls.__obj=object.__new__(cls)
    return cls.__obj
    def __init__(self):
    pass

    # 第一次实例化对象,因为cls.__obj is None 条件为真,创建对象并返回
    obj1=SingTon()
    # 第二次发现 cls.__obj is None: 条件为假,直接返回原有对象
    obj2=SingTon()
    # 第三次发现 cls.__obj is None: 条件为假,直接返回原有对象
    obj3=SingTon()
    print(obj1) #<__main__.SingTon object at 0x00000000027986A0>
    print(obj2) #<__main__.SingTon object at 0x00000000027986A0>
    print(obj3) #<__main__.SingTon object at 0x00000000027986A0>
    #2. 有且只有一个对象
    class SingTon():
    # 防止类外调用__obj,形成封装保护.
    __obj = None
    def __new__(cls, *args, **kwargs):
    if cls.__obj is None:
    cls.__obj=object.__new__(cls)
    return cls.__obj
    def __init__(self,name):
    self.name=name
    obj1=SingTon("Alex")
    obj2=SingTon("Jack")
    obj3=SingTon("Jane")
    print(obj1.name) #Jane
    print(obj2.name) #Jane
    print(obj3.name) #Jane
    7.# ###__del__魔术方法(析构方法)
    import os
    """
    触发时机:当对象被内存回收的时候,自动触发[1.页面执行完毕,回收所有变量;2.所有对象被del的时候]
    功能:对象使用完毕后资源回收
    参数:一个self接受对象
    返回值:无
    """
    class LangDog():
    def __init__(self,name):
    self.name=name
    def eatmeat(self):
    print("可爱的小狼狗喜欢吃肉")
    def __del__(self):
    print("析构方法被触发!")

    obj=LangDog("Janmes.dandan")
    #(1).页面执行完毕,回收所有变量;
    print("======程序执行完毕start=======")

    #(2)所有对象被del的时候
    obj2=obj #两个不同的对象指向同一个对象
    print(obj2)
    print(obj)
    del obj
    print("======程序执行完毕end=======")

    #(3)文件读取操作
    """
    fp=open("文件名",mode="r",encoding="utf-8")
    res=fp.read()
    fp.close()
    """
    class ResdFile():
    def __new__(cls, filename):
    if os.path.exists(filename):
    return object.__new__(cls)
    return print("该文件不存在")
    def __init__(self,filename):
    self.fp=open(filename,mode="r",encoding="utf-8")

    def readcontent(self):
    res=self.fp.read()
    return res

    def __del__(self):
    fp.close()

    obj=ResdFile("ceshi111.txt")
    res=obj.readcontent()
    print(res)
    8.# ###__str__  魔术方法
    """
    触发时机:使用print(对象)或者str (对象)的时候触发
    功能: 查看对象
    参数:一个self接受当前对象
    返回值:必须返回字符串类型
    """
    class Cat():
    gift="抓老鼠"
    def __init__(self,name):
    self.name=name
    def obj_info(self):
    return "该对象名字{},它天生属性是{}".format(self.name,self.gift)
    def __str__(self):
    return self.obj_info()
    tom=Cat("汤姆")
    #方式一:打印对象时触发
    print(tom) #该对象名字汤姆,它天生属性是抓老鼠
    #方法二:强转对象为字符串时,触发
    res=str(tom)
    print(res) #该对象名字汤姆,它天生属性是抓老鼠
    9.###__repr__ 魔术方法
    """
    触发时机:使用repr(对象)的时候触发
    功能: 查看对象
    参数:一个self接受当前对象
    返回值:必须返回字符串类型
    """
    class Mouse():
    gift="会打洞"
    def __init__(self,name):
    self.name=name

    def obj_info(self):
    return "该对象名字{},该对象属性:龙生龙,凤生凤,老鼠的儿子{}".format(self.name,self.gift)

    def __repr__(self):
    return self.obj_info()
    #系统底层,自动加了一句话,如果存在__repr__魔术方法,自动把这个方法赋值给__str__方法,所以即使在print打印或者强转对象为字符串,也仍然触发
    __str__=__repr__
    jerry=Mouse("杰瑞")
    res=repr(jerry)
    print(res) #该对象名字杰瑞,该对象属性:龙生龙,凤生凤,老鼠的儿子会打洞

    res=str(jerry)
    print(res) #该对象名字杰瑞,该对象属性:龙生龙,凤生凤,老鼠的儿子会打洞
    10.###__call__魔术方法
    import math
    """
    触发时机:把对象当做函数调用的时候自动触发
    功能: 模拟函数化操作
    参数:参数不固定,至少一个self参数
    返回值:看需求
    """
    #(1)基本语法
    class MyClass():
    def __call__(self):
    print("__call__方法被调用")
    obj=MyClass()
    obj()

    #(2)__call__魔术方法可以做一个统一的调用
    class MakeCake():
    def __call__(self,something):
    print("我做的东西是{}".format(something))
    self.step1()
    self.step2()
    self.step3()

    def step1(self):
    print("和面,发酵,放点糖,放牛奶,等一天")
    def step2(self):
    print("扔进烤箱,考七七四十九天,炼丹")
    def step3(self):
    print("拿出来,切一切吃")

    obj=MakeCake()
    obj("蛋糕")
    # obj.step1()
    # obj.step2()
    # obj.step3()

    #(3) 默认系统int这个方法的实现
    # int 浮点型 纯数字 字符串 布尔类型 它自己
    class MyInt():
    def func(self,strvar):
    res=strvar.lstrip("0")
    if res=='':
    return 0
    print(res)
    return eval(res)
    def __call__(self, num):
    if isinstance(num,bool):
    if num==True:
    return 1
    else:
    return 0
    elif isinstance(num,int):
    return num
    elif isinstance(num,float):
    if num<0:
    return math.ceil(num)
    else:
    return math.floor(num)
    elif num.isdecimal():
    self.func(num)
    else:
    print("该类型不能判断")


    myint=MyInt()
    print(myint(False)) #0
    print(myint(True)) #1
    print(myint(4444))
    print(myint(-3.15)) #3
    print(myint("000000123")) #123
    print(myint("000000000"))
    print(myint("000000090")) #90
    11.###__bool__魔术方法
    """
    触发时机:使用bool(对象)的时候触发
    功能: 强转对象
    参数:一个self接受当前对象
    返回值:必须是bool类型
    """
    class MyClass():
    def __bool__(self):
    return True
    obj=MyClass()
    res=bool(obj)
    print(res)

    12.###__add__魔术方法 (与之相关的__add__反向加法)
    """
    触发时机:使用对象进行运算相加的时候自动触发
    功能: 对象运算
    参数:两个对象参数
    返回值:运算后的值
    """
    class MyClass():
    def __init__(self,num):
    self.num=num
    #当对象在+加号的左侧时,自动触发;
    def __add__(self,other):
    return self.num*2+other

    def __radd__(self, other):
    return self.num*3+other
    a=MyClass(3)
    #self接收到a,other 接收到1 self.num*2+1=3*2+1=7
    res=a+1
    print(res)

    b=MyClass(5)
    #第一次参数永远接受的是对象,self接收的b,other接收的是2 ==>, 5*3+2=17
    res=2+b
    print(res)

    #a+b
    """
    先触发add魔术方法,self接受到a,other接收到b 3*2+b==>6+b
    6+b 再次触发了radd魔术方法 self接收到b other 接收到6 5*3+6=21
    """

    res=a+b
    print(res)
    13.###__len__魔术方法
    """
    触发时机:使用len(对象)的时候自动触发
    功能: 用于检测对象中或者类中某个内容的个数
    参数:一个self接受当前对象
    返回值:必须返回整型
    """
    class MyClass():
    pty1=1
    __pty2=2
    pty3=3
    def func1(self):
    pass
    def func2(self):
    pass
    def __func3(self):
    pass
    def __len__(self):
    dic = MyClass.__dict__
    lst=[i for i in dic if not(i.startswith("__") and (i.endswith("__")))]
    return len(lst)
    """
    lst=[]
    for i in dic:
    if not(i.startswith("__") and (i.endswith("__"))):
    lst.append(i)
    """
    obj=MyClass()
    print(len(obj))
    14.####装饰器
    """
    替换旧函数,返回新函数,在不改变原有代码的前提下,为原函数拓展新功能
    语法:@(语法糖)
    """
    #装饰器的原型
    def kuozhan(func):
    def newfunc():
    print("厕所前,蓬头垢面")
    func()
    print("厕所后,精神抖擞")
    return newfunc
    def func():
    print("我是高富帅")
    """
    把旧函数当成参数传递给kuozhan,返回一个新函数newfunc赋值给func
    func由以前的旧函数变成了现在的新函数,就间接完成了功能上的拓展
    而没有改变原代码
    """
    func=kuozhan(func) #func ===> newfunc===>func() <=======>newfunc()
    func()
    print("---------------")
    #2.装饰器的基本写法
    def kuozhan(func):
    def newfunc():
    print("厕所前,蓬头垢面")
    func()
    print("厕所后,精神抖擞")
    return newfunc
    @kuozhan
    def func():
    print("我是高富帅")
    func()
    """
    @有两个功能:
    1.可以吧下面的func()当成参数传递给装饰器kuozhan
    2.把kuozhan函数返回的新函数,用来替换旧函数func,
    相当于func=kuozhan(func)一模一样
    """
    #3.装饰器的嵌套
    def kuozhan1(func):
    def newfunc():
    print("厕所前,蓬头垢面1")
    func()
    print("厕所后,精神抖擞2")
    return newfunc

    def kuozhan2(func):
    def newfunc():
    print("厕所前,饥肠辘辘3")
    func()
    print("厕所后,酒足饭饱4")
    return newfunc
    @kuozhan2
    @kuozhan1
    def func():
    print("我是个屌丝!")

    func()

    """
    首先把func当成参数传递给kuozhan1这个装饰器
    返回:
    def newfunc():
    print("厕所前,蓬头垢面")
    func()
    print("厕所后,精神抖擞")
    变成下面的样子
    @kuozhan2
    def newfunc():
    print("厕所前,饥肠辘辘")
    func() #把上一次装饰的函数拿到这里
    print("厕所后,酒足饭饱")
    结果为:3124
    """
    print("--------------------")
    #4.带有参数的装饰器
    """
    原函数是几个参数,拓展之后就是几个参数
    """
    def kuozhan(func):
    def newfunc(who,where):
    print("厕所前,衣衫褴褛")
    func(who,where)
    print("厕所后,衣冠禽兽")
    return newfunc
    @kuozhan
    def func(who,where):
    print("{}在{}解手.....!".format(who,where))
    func("李祖清","鸟窝")
    print("------------------")
    #5.带有参数返回值的装饰器
    def kuozhan(func):
    def newfunc(*args,**kwargs): #*和**的魔术用法
    print("厕所前,冷冷清清")
    res=func(*args,**kwargs)
    print("厕所后,满嘴雌黄")
    return res
    return newfunc
    @kuozhan
    def func(*args,**kwargs):
    lst = []
    dic={"lzq":"李祖清","wb":"吴波","sl":"帅了"}
    print(args)
    # print(kwargs)
    """
    for k,v in kwargs.items():
    if k in dic:
    # print(k,v)
    res=dic[k] + "留下了" +v
    lst.append(res)
    """
    #用推导式
    lst=[dic[k] + "留下了" + v for k, v in kwargs.items() if k in dic ]
    return lst
    # print(lst)


    # func(lzq="15g",wb="15kg",sl="15t")
    res=func("电影院","游泳池","鸟窝",lzq="15g",wb="15kg",sl="15t",lt="15mg")
    print(res)
    15.###类中方法:
    """
    普通方法:没有任何参数,只能类来调用
    绑定方法:
    (1)绑定到对象
    (2)绑定到类
    静态方法:
    无论对象还是类都能调用
    """
    class Dog():
    def jiao():
    print("小狗喜欢叫")
    #绑定方法(绑定对象)
    def run(self):
    print("小狗喜欢跑")
    #绑定方法(绑定类)
    @classmethod
    def tail(cls):
    print("小狗看见主人摇尾巴")
    #静态方法
    @staticmethod
    def tian():
    print("小狗看见骨头喜欢舔一舔")
    #实例化对象
    obj=Dog()
    #1.普通方法
    Dog.jiao()

    #2.绑定方法(绑定对象)
    obj.run()
    Dog.run(1) #手动传参

    #3.绑定方法(绑定到类)
    """无论是类还是对象都可以调用,只不过默认传递的参数是类。"""
    obj.tail()
    Dog.tail() #推荐

    #4.静态方法
    obj.tian()
    Dog.tian()

    #默认在类外,动态添加的方法是静态方法
    obj.func=lambda :print(12333)
    obj.func()

    # import types (复习)
    # types.MethodType

  • 相关阅读:
    AGC023C Painting Machines
    LG3834 可持久化线段树1
    又是一天
    ARC103F Distance Sums
    CF1053E Euler tour
    UOJ22 外星人
    洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)
    洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)
    CF49E Common ancestor(dp+dp+dp)
    洛谷4051 JSOI2007 字符加密(SA)
  • 原文地址:https://www.cnblogs.com/vivian0119/p/11324891.html
Copyright © 2020-2023  润新知