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)