zoukankan      html  css  js  c++  java
  • 9.多继承、类的特殊方法、装饰器

    1.多继承

    当继承的类有同种方法的时候,只会继承前面一个的方法。调用父类方法super()

    #1.多继承
    
    class Base:
        def play(self):
            print('这是Base')
    
    
    class A(Base):
        def play(self):
            print(type(self))
            print('这是A')
    
    
    class B(Base):
        def play(self):
            print('这是B')
    
    
    class C(A,B):
        
        #子类调用父类方法
        def play(self):
            #A.play(self)  #第一种方法
            #B.play(self)
    
            #super().play()     #第二种方法,默认调用第一个父类方法
            #super(C,self).play() #括号不写,默认(C,self)
    
            #super(A,self).play()  # Base
            #super(B,self).play()   # A   ,  上一层
            #super(Base,self).play()
            print('这是C')
    
            
    
    c = C()  # (B,A)  C  -> B  -> A  -> Base  ->object
    
             # (A,B)  C  -> A  -> B  -> Base  ->object
    
    C().__class__.mro()
    
    '''
    super, 上一层
    1.super(),    (自己类名,自己实例) 例:( C,c )
    
    2. 谁调用我,我就以你为基准。 建立一张调用顺序表
        ‘(B,A)   C  -> B  -> A  -> Base  ->object ’
    
    
    '''

    2.类的特殊方法

    #类属性:
        __dict__     # 类的属性(包含一个字典,由类的数据属性组成)
        __doc__     # 类的文档字符串
    #类方法:  
        __init__    # 初始化
        __repr__    # 直接返回这个对象  repr() 函数就是调用对象的这个方法
        __str__     # print(obj) 如果类里面定义了__repr__,没有定义__str__ print(obj)也会返回__repr__的内容,或者说__repr__的优先级更高
        __call__    # Obj() 使实例可被调用
        
    #运算符方法
        __add__(self,other)     #x+y
        __sub__(self,other)     #x-y 
        __mul__(self,other)     #x*y  
        __mod__(self,other)     #x%y
        __iadd__(self,other)    #x+=y
        __isub__(self,other)    #x-=y 
        __radd__(self,other)    #y+x
        __rsub__(self,other)    #y-x 
        __imul__(self,other)    #x*=y 
        __imod__(self,other)    #x%=y 
        
    #和类有关的几个函数  
        delattr()        # 删除对象属性
        getattr()        # 得到某个属性值
        setattr()        # 给对象添加某个属性值
        hasattr()          # 判断对象object是否包含名为name的特性
        isinstance()      # 检查对象是否是类的对象,返回True或False
        issubclass()      # 检查一个类是否是另一个类的子类。返回True或False    
    '''
    不仅仅是属性,更多是方法
    
    '''
    
    class Rectangle:
        '''这是一个长方形类,它可以计算面积'''
        aaa = 1
        def __init__(self,length,width):     #构造方法
            if isinstance(length,(int,float)) and isinstance(width,(int,float)):
                self.length = length
                self.width = width
            else:
                print('请输入int or float')
    
        def area(self):
            return self.length * self.width
    
    ##    def __str__(self):
    ##        return  '这个长方形的面积%s'%self.area()
    
        def __repr__(self):
            return '长:%s  宽:%s'%(self.length,self.width)
    
        def __call__(self):
            return '我这是一个Rectangle 类,你要干嘛'
    
        def __add__(self,other):
            return self.area() + other.area()
            
        def __sub__(self,other):
            return '不可以相减'
    
    
        
    r = Rectangle(2,3)
    
    #类属性
    
    #__dict__ 
    
    r.__dict__   # 打印实例里面的属性 ,{'length': 2, 'width': 3}
    
    
    #注意  ,共有属性。当不修改时,默认引用(源类 Rectangle ),
                    # 修改之后,就会定义在 实例里面
    r.aaa = 22
    r.__dict__
    
    
    #__doc__
    r.__doc__
    
    
    #类方法 
    
    #__str__    
    #print(r)
    
    #__repr__
    r
    
    '%s'%'ssss'   
    '%r'%'rrrr'
    
    #print  默认调用__str__   ,没有时__repr__
    
    
    
    
    ####  __call__
    #r()
    r()  # '我这是一个Rectangle 类,你要干嘛'
    
    def dd():
        print('dd')
    
    dir(dd)   #'__call__'
    
    
    
    r1 = Rectangle(2,4)
    r2 = Rectangle(3,5)
    
    #   __add__(self,other)
    
    
    #__sub__(self,other)     #x-y 
    
    
    
    
    ####
    '''
    delattr()        # 删除对象属性
    getattr()        # 得到某个属性值
    setattr()        # 给对象添加某个属性值
    hasattr()          # 判断对象object是否包含名为name的特性
    isinstance()      # 检查对象是否是类的对象,返回True或False
    issubclass()      # 检查一个类是否是另一个类的子类。返回True或Fals
    '''

    3.装饰器

    装饰器(deco):
        装饰函数的参数是被装饰的函数对象,返回原函数对象装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象
        概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
    ###3.装饰器 ,添加附加功能
    
    #闭包
    
    def fx(x):
        x += 1
        def fy(y):
            return x*y
        
        return fy
    
    '''
    fx(1)(2)
    temp = fx(1)
    temp(2)
    '''
    
    
    def f1(func):
        print('f1 running')
        def f2(y):
            print('f2 running')
            return func(y)+1
        return f2
        
    
    def gun(m):
        print('gun running')
        return m*m
    
    '''
    f1(gun)
    temp = f1(gun)
    temp(5)
    '''
    
    
    @f1
    def gun2(m):
        print('gun running')
        return m*m
    
    '''
    1.  @f1  ->   f1( gun2 )   -> f2
    2.  f2  ,等待调用
    3.  gun2   (5)  ->  当参数 5传入 --> f2(5)
    4.  f2(5), 开始运行  ->  print('f2 running') ->  func(y): func = gun2  y = 5  ->{{func(y) 等于 gun2(5)}}
    5.  gun2(5) 开始运行  -> print('gun running') ->  25
    6.  25 +1  -> 26
     
    '''
    
    
    
    ##测试时间
    
    '''
    import time   
    def run_time(func):
        def new_fun(*args,**kwargs):
            t0 = time.time()
            print('star time: %s'%(time.strftime('%x',time.localtime())) )
            back = func(*args,**kwargs)
            print('end time: %s'%(time.strftime('%x',time.localtime())) )
            print('run time: %s'%(time.time() - t0))
            return back
        return new_fun
    
    '''
    
    
    import time  #不要纠结
    
    def run_time(func):
        def new_fun():
            t0 = time.time()
            print('star time: %s'%(time.strftime('%x',time.localtime())) )
            func()
            print('end time: %s'%(time.strftime('%x',time.localtime())) )
            print('run time: %s'%(time.time() - t0))
            
        return new_fun
    
    
    
    @run_time
    def test():
        for i in range(1,10):
            for j in range(1,i+1):
                print('%dx%d=%2s'%(j,i,i*j),end = ' ')
            print ()
    
            
    ##########  留个映像,用的不是很多

    4.类装饰器

    @property 
        装饰过的函数返回的不再是一个函数,而是一个property对象
        装饰过后的方法不再是可调用的对象,可以看做数据属性直接访问。
    
    @staticmethod #(静态方法)
        把没有参数的函数装饰过后变成可被实例调用的函数,      
        函数定义时是没有参数的,可以不接收参数
    
    @classmethod (类方法)
        把装饰过的方法变成一个classmethod类对象,既能能被类调用又能被实例调用。
        注意参数是cls代表这个类本身。而是用实例的方法只能被实例调用。     
            
    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
    而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
    这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁
    ##类装饰器
    class Test_Class():
        def __init__(self,func):
            self.func = func
    
        def __call__(self):
            print('')
            return self.func
    
    
    @Test_Class
    def  test():
        print('这是一个测试')
    
    test()  #    self.func : test 函数体
    test()()

    # 1. @Test_Class : Test_Class( test ) -> 相当于:t = Test_Class( test )
    # 2. test() -> 相当于: t() 调用实例的call方法 -> 返回 self.func函数体
    # 3. test()() 调用test()

    ###python自带3个,类的内置装饰器
    class Rectangle:
        '''这是一个长方形类,它可以计算面积'''
        aaa = 1
        def __init__(self,length,width):     #构造方法
            if isinstance(length,(int,float)) and isinstance(width,(int,float)):
                self.length = length
                self.width = width
            else:
                print('请输入int or float')
    
        @property  # 可以把方法,当成属性一样调用  , r.area
        def area(self):
            return self.length * self.width
        
        @staticmethod   #静态方法, 不用self了,实例可以直接调用
        def func():
            print('可以调用吗?')
    
        @classmethod   #将实例,还原成了类cls   self实例
        def show(cls):
            print(cls)
            print('show fun')
    
    
    r = Rectangle(2,3)

    5.作业

    1.测试type 和 isinstance 那个的速度更快

    import time
    
    def run_time(func):
        def new_fun():
            t0 = time.time()
            print(t0)
            func()
            t1 = time.time() - t0
            return t1
        return new_fun
    
    @run_time
    def test_type():
        for i in range(100):
            i = i*2
            type(i) == int
        print('结束')
    
    @run_time
    def test_isinstance():
        for i in range(100):
            i = i*2
            isinstance(i,(int,float))
        print('结束')
    
    def test():
        a=test_type()   #t1
        b=test_isinstance()  #t1
        if a>b:
            print('isinstance更快')
        else:
            print('type更快')
        
    View Code

    2.实现一个正方形类的加减乘除(就那些魔术方法,能写多少写多少)

    class Square(object):
        def __init__(self,length):
            self.length = length
            self.area = length**2
    
        def __add__(self,other):   #  __add__ 
            return self.area + other.area
    
        def __sub__(self,other):
            return self.area - other.area
    
        def __mul__(self,other):
            return self.area * other.area
    
        def __truediv__(self,other):
            return self.area / other.area
    View Code
  • 相关阅读:
    LDA的整体流程
    java中字符串的用法
    verification Code
    properties
    Hash
    substring的问题
    LDA和PLSA的区别
    Step By Step(Lua环境)
    Step By Step(Lua调用C函数)
    Step By Step(Lua弱引用table)
  • 原文地址:https://www.cnblogs.com/woaixuexi9999/p/9215609.html
Copyright © 2011-2022 走看看