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

猜你喜欢

转载自www.cnblogs.com/vivian0119/p/11324891.html