1.继承
1.1 单继承# ### 继承 """ (1) 单继承 (2) 多继承 至少2个类,子类和父类 一个类继承另外一个类,当前类是子类 (衍生类) 被继承的这个类是父类.(基类,超类) python 所有类的父类都是object """ # 1.子父继承后,子类可以使用父类的公有方法 class Father(): skin = "黑色的" __sex = "男性" 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) #error obj = Son() # print(obj.__sex) # obj.pub_func() # 3.子父继承后,子类可以改写父类方法 """self对象优先调用本类中的方法,如果本类当中没有再调用父类.""" class n_selfchild(Father): skin = "白色的" def hobby(self): print("白种人喜欢种大麻") obj = n_selfchild() obj.hobby()1.2 多继承
# ### 多继承 # 1.基本语法 class Father(): f_property = "英俊潇洒,才华横溢,道貌岸然,一表人才" def hobby1(self): print("抽烟,喝酒,烫头,吃喝嫖赌抽,坑蒙拐骗偷") class Mother(): m_property = "一枝红情出墙来" def hobby(self): print("打麻将,蹦野迪,买包包") class Daughter(Father,Mother): pass obj = Daughter() print(obj.f_property) obj.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) Father.hobby1() """ # self 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()
1.3 菱形继承
# ### 菱形继承 (钻石继承) """ Human Man Woman Children """ class Human(): pty = 4 def feelT(self): print("古代人类,天冷了,穿动物的毛1") print(self.pty) # 1 print("古代人类,天热了,啃树皮2") class Man(Human): pty = 3 def feelT(self): print("现代人类,天热了,喝啤酒,吃西瓜,撸串3") super().feelT() print("现代人类,天冷了,把火罐,开空调,吃炸鸡4") class Woman(Human): pty = 2 def feelT(self): print("现代女性,天热了,光膀子,穿裙子,买包包5") super().feelT() print("现代女性,天冷了,穿动物的毛,貂皮大衣6") class Children(Man,Woman): pty = 1 def feelT(self): print("现代小孩,天热了,吃冰棍,游泳7") super().feelT() print("现代小孩,天冷了,喝热水,玩农药8") obj = Children() obj.feelT() """ super 遵循mro列表中出现顺序,依次进行调用. 类.mro() super在调用方法时,默认传递本对象. """ lst = Children.mro() print(lst) ''' super 在调用同名方法时,要依据该列表中出现的类的调用顺序,依次调用 [<class '__main__.Children'>, <class '__main__.Man'>, <class '__main__.Woman'>, <class '__main__.Human'>, <class 'object'>] ''' """ 现代小孩,天热了,吃冰棍,游泳7 现代人类,天热了,喝啤酒,吃西瓜,撸串3 现代女性,天热了,光膀子,穿裙子,买包包5 古代人类,天冷了,穿动物的毛1 古代人类,天热了,啃树皮2 现代女性,天冷了,穿动物的毛,貂皮大衣6 现代人类,天冷了,把火罐,开空调,吃炸鸡4 现代小孩,天冷了,喝热水,玩农药8 """ #issubclass 判断子父关系 isinstance 判断类型 res = issubclass(Man,Human) print(res) # 判断子父时,必须是类,不能是对象 # res = issubclass(obj,Human) # print(res) # 判断子父时,有继承血缘关系即可. res= issubclass(Children,Human) print(res) # 判断Children,在小括号中,有一个满足是父类就返回真 res= issubclass(Children,(Woman,Man,Human)) print(res) #obj的类型是Children , 只要有血缘关系即可 ,一脉相承. res= isinstance(obj,Children) print(res) res= isinstance(obj,Woman) print(res) res= isinstance(obj,Human) print(res) res= isinstance(obj,(Human,Man)) print(res)
2.单态
# ### 单态模式 """类无论实例化多少次,都有且只有一个对象. 为了节省空间""" # 1.基本语法 class SingleTon(): # 防止类外调用__obj,形成封装保护. __obj = None def __new__(cls): if cls.__obj is None: obj = object.__new__(cls) cls.__obj = obj return cls.__obj # 第一次实例化对象,因为cls.__obj is None 条件为真,创建对象并返回 obj1 = SingleTon() # 第二次发现 cls.__obj is None: 条件为假,直接返回原有对象 obj2 = SingleTon() # 第二次发现 cls.__obj is None: 条件为假,直接返回原有对象 obj3 = SingleTon() print(obj1) print(obj2) print(obj3) # 2. 有且只有一个对象 class SingleTon(): # 防止类外调用__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 = SingleTon("郭一萌") print(obj1.name) obj2 = SingleTon("舒则会") print(obj1.name) print(obj2.name) obj3 = SingleTon("银燕") print(obj1.name) print(obj2.name) print(obj3.name) """ obj1.name = 郭一萌 obj2.name = 舒则会 """
3.多态
# ### 多态 """ 不同的子类对象,调用相同的父类方法,产生不同的执行结果 继承,重写 好处:多态针对的是对象来说的.在不改变原有代码的前提下,完成不同的功能; 不同的对象,调用相同的方法,达到了不同的功能. """ 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() # 各就位准备 lst = [obj_army,obj_navy,obj_airforce] # 将军请下令 strvar = ''' 1.全体出击 2.全体撤退 3.空军上,其他人撤退 ''' 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("欢迎下次在指挥") break
4.魔术方法
4.1 __new__ 魔术方法 ''' 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值:通常返回对象或None ''' """ 对象.属性 对象.方法() 类.属性 类.方法() object是所有类的父类 """ # (1)基本语法 class MyClass(object): a = 5 obj2 = MyClass() # 可以通过__new__ 来控制对象创建的过程 class MyClass2(): def __new__(cls): print(cls) # 通过父类object 中的 __new__ 魔术方法 ,返回该类的对象,参数是类. # obj = object.__new__(cls) # 返回本类对象,只能通过父类创建. # return obj # 可以返回None # return None # 也可以返回别人的对象 return obj2 obj = MyClass2() print(obj) print(obj.a) # 2 .对比__new__ 和 __init__ 之间的区别 """ __new__ 负责创建对象 __init__ 负责初始化对象 __new__ 在 __init__ 触发时机之前. """ class MyClass3(): def __new__(cls): print(1) return object.__new__(cls) def __init__(self): print(2) self.name = "王刚蛋" obj = MyClass3() # __new__ 和 __init__ 形参实参要匹配 class MyClass3(): def __new__(cls,name): print(1) return object.__new__(cls) def __init__(self,name): print(2) self.name = name obj = MyClass3("廖平平") print(obj.name) # 升级版 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("廖平平",98,"未知") print(obj.name) print(obj.age) print(obj.sex) # (3) 注意点.__init__ 只能初始化自己本类的对象 class MyClass4(): def __new__(cls): print(1) return obj2 # 不会调用init方法,因为返回的对象不是MyClass4本身的,不调用; def __init__(self): print(2) obj = MyClass4() print(obj) 4.2 __del__ 魔术方法 (析构方法)
''' 触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候] 功能:对象使用完毕后资源回收 参数:一个self接受对象 返回值:无'''import osclass LangDog(): def __init__(self,name): self.name = name def eatmeat(self): print("可爱滴小狼狗喜欢吃肉") def __del__(self): print("析构方法被触发")obj = LangDog("詹姆斯•蛋蛋")# (1) 页面执行完毕,触发析构方法print("<====程序执行完毕start===>")# (2)所有对象被del的时候obj2 = obj # 两个不同的变量 指向同一个对象print(obj2)print(obj)del objdel obj2print("<====程序执行完毕end===>")# (3)文件读取操作"""fp = open("文件名",mode="r",encoding="utf-8")res = fp.read()fp.close()"""class ReadFile(): 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): self.fp.close()obj = ReadFile("ceshi111.txt")res = obj.readcontent()print(res)
4.3 __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)#__repr__ 魔术方法''' 触发时机: 使用repr(对象)的时候触发 功能: 查看对象,与魔术方法__str__相似 参数: 一个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)print(jerry)res = str(jerry)print(res)
4.3 __bool__ 魔术方法''' 触发时机:使用bool(对象)的时候自动触发 功能:强转对象 参数:一个self接受当前对象 返回值:必须是布尔类型'''class MyClass(): def __bool__(self): return False # 实例化对象obj = MyClass() res = bool(obj)print(res) '''类似的还有如下等等(了解): __complex__(self) 被complex强转对象时调用 __int__(self) 被int强转对象时调用 __float__(self) 被float强转对象时调用 ... ...''' 4.4 __add__ 魔术方法 (与之相关的__radd__ 反向加法)''' 触发时机:使用对象进行运算相加的时候自动触发 功能:对象运算 参数:二个对象参数 返回值:运算后的值''''''类似的还有如下等等(了解): __sub__(self, other) 定义减法的行为:- __mul__(self, other) 定义乘法的行为: __truediv__(self, other) 定义真除法的行为:/ ... ...'''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 + othera = MyClass(3)# self 接收到 a ,other 接收到 1 self.num * 2 + 1 = 3 * 2 +1 = 7res = a+1print(res)b = MyClass(5)# 第一次参数永远接受的是对象,self接收的 b ,other 接受的是 2 => 5 * 3 + 2 => 17res = 2 + bprint(res)# a+b"""先触发add魔术方法 self 接收到a other 接收到b => 3 * 2 + b => 6 +b6+b 有触发了radd魔术方法 self 接收到 b other 接收到6 => 5 * 3 + 6 => 21"""res = a+bprint(res)4.5 __len__ 魔术方法''' 触发时机:使用len(对象)的时候自动触发 功能:用于检测对象中或者类中某个内容的个数 参数:一个self接受当前对象 返回值:必须返回整型''''''类似的还有如下等等(了解): __iter__(self) 定义迭代容器中的元素的行为 __reversed__(self) 定义当被 reversed() 调用时的行为 __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为 ... ...''' # 计算类中的成员个数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 = [] for i in dic: if not( i.startswith("__") and i.endswith("__") ): lst.append(i) """ lst = [i for i in dic if not( i.startswith("__") and i.endswith("__") )] return len(lst)obj = MyClass()print(len(obj))
4.6 __call__ 魔术方法''' 触发时机:把对象当作函数调用的时候自动触发 功能: 模拟函数化操作 参数: 参数不固定,至少一个self参数 返回值: 看需求'''import math# (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("扔进烤箱,考7749天,炼丹") def step3(self): print("拿出来,切一切吃") obj = MakeCake()obj("蛋糕")# (3) 默认系统int这个方法的实现# int 浮点型 纯数字字符串 布尔类型 它自己class MyInt(): def func(self,strvar,sign=1): res = strvar.lstrip("0") if res == '': return 0 # print(res) # 左边计算的是数值, 右边是正负号,用来控制这个数字的正负; return eval(res) * sign 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) # +000000000012345 -000000000012345 elif (num[0] == "+" or num[0] == "-") and num[1:].isdecimal(): if num[0] == "+": sign = 1 else: sign = -1 return self.func(num[1:],sign) # 000000000012345 elif num.isdecimal(): return self.func(num) else: print("该类型不能判断") myint = MyInt()print(myint(444))print(myint(9.9))print(myint(-9.9))# int(True) => 1# int(False) => 0# import math# print(math.ceil(-4.9))# print(math.floor(-3))# print(math.ceil(4.9))# print(math.floor(-9.9)) # -10# print(math.ceil(-9.9)) # -9# print(int("000000123"))# print(eval("123"))# print(eval("000000000123"))print(11)print(myint("+0000000000123456"))print(myint("000000000123457"))print(int(+-+-+-+-90))print(myint(int(+-+-+-+-90)))
5. 装饰器
# ### 装饰器 """ 替换旧函数,返回新函数,在不改变原有代码的前提下,为原函数拓展新功能 语法:@ (语法糖) """ # 1.装饰器的原型 def kuozhan(func): def newfunc(): print("厕所前,蓬头垢面") func() print("厕所后,精神抖擞") return newfunc def func(): print("我是高富帅") """ 把旧函数当成参数传递给kuozhan,扩展返回一个新函数newfun赋值给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("我是白富美") """ @ 有两个功能: 1.可以把下面的func当成参数传递给装饰器kuozhan 2.把kuozhan函数返回的新函数,用来替换旧函数func. 相当于 func = kuozhan(func) 一模一样. """ 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("厕所前,蓬头垢面1") func() print("厕所后,精神抖擞2") 变成下面的样子: @kuozhan2 def newfunc(): print("厕所前,蓬头垢面1") func() print("厕所后,精神抖擞2") def newfunc(): print("厕所前,饥肠辘辘3") func() # 把上一次装饰的函数拿到这里 print("厕所前,蓬头垢面1") func() print("厕所后,精神抖擞2") print("厕所后,酒足饭饱4") # 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): print(args) print("我来了,老弟") # lst = [] dic = {"lzq":"李祖庆","wb":"吴波",'sl':"帅乐"} """ print(args) print(kwargs) for k,v in kwargs.items(): if k in dic: res = dic[k]+"留下了"+v lst.append(res) """ # 用推导式转化 lst = [dic[k]+"留下了"+v for k,v in kwargs.items() if k in dic] return lst res = func("电影院","游泳池","鸟窝",lzq="15克",wb="15斤",sl="15吨",lt="15两") print(res)
6. 类中方法
# ### 类中方法 """ 普通方法: 没有任何参数,只能类来调用 绑定方法: (1) 绑定到对象 (2) 绑定到类 静态方法: 无论对象还是类都能调用 """ class Dog(): # 普通方法 def jiao(): print("小狗喜欢叫") # 绑定方法(绑定对象) def run(self): print("小狗跑的快") # 绑定方法(绑定到类) @classmethod def tail(cls): print(cls) print("小狗看见主人会摇尾巴") # 静态方法 @staticmethod def tian(a): print("小狗看见骨头喜欢舔一舔") # 实例化对象 obj = Dog() # 1.普通方法 Dog.jiao() # 2.绑定方法(绑定对象) obj.run() Dog.run(1) # 手动传参 # 3.绑定方法(绑定到类) """无论是类还是对象都可以调用,只不过默认传递的参数是类.""" Dog.tail()# 推荐 obj.tail() # 4.静态方法 obj.tian(2) Dog.tian(3) # 默认在类外,动态添加的方法时静态方法; obj.func = lambda : print(1233) obj.func() # import types # types.MethodType(func,obj)