Day7

本秂侑毒 提交于 2019-11-26 20:34:52

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)

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!