zoukankan      html  css  js  c++  java
  • 【Python043-魔法方法:算术方法2】

    一、 反运算符

    当对应的操作数不支持调用时,反运算数被调用(参考资料Lhttps://fishc.com.cn/thread-48793-1-1.html )

    1、对象(a+b)相加,如果对象a有__add__方法,请问b对象__radd__方法会被调用吗?

    不会被调用

    >>> class Iinit(int):
        def __radd__(self,other):
            print('__radd__被调用!')
            return int.__sub__(self,other)
    
        
    >>> a = Iinit('5')
    >>> b = Iinit('3')
    >>> a+b
    8
    >>> 1+b
    __radd__被调用!
    2
    >>> 
    
    #a+b时,调用了__add__,则你不会调用__radd__
    
    #1+b时,由于没有找到__add__,则调用了__radd__    (何时调用__radd__方法:当a对象的__add__没有实现或者不支持相应操作时,b会自动调用__radd__方法

    2、如何在继承中调用基类的方法

    基类的方法:在程序中,继承描述的多个类之间的关系,如果一个类A中的方法和属性可以被复用,就可以通过继承传递到B类,A类就被称为父类也叫做基类,那么B类就被称为子类也叫派生类

    #子类可以直接调用父类的属性和方法
    class A:
        def __init__(self):
            self.study='学习打卡第一天!'
    
        def learn(self):
            print('为梦想奋斗!')
    
    class B(A):
        def catch(self):
            print('喝一壶老酒让我回回头!')
    
    b = B()
    b.learn()
    b.catch()
    print(b.study)
    
    为梦想奋斗!
    喝一壶老酒让我回回头!
    学习打卡第一天!
    >>> 

    使用super这个BIF

    class Base:
        def __init__(self):
            print(' this is function of Base!')
    
    class A(Base):
        def __init__(self):
            super().__init__()
            print('this is function of A')
    
    class B(Base):
        def __init__(self):
            super().__init__()
            print('this is function of B')
    
    class C(A,B):
        def __init__(self):
            super().__init__()
            print('this is function of C')
    
    c = C()
    
    打印输出:
     this is function of Base1
    this is function of B
    this is function of A
    this is function of C

    为什么super()函数重写之后,Base()函数只调用了一次初始化函数

    要理解为什么会这样,首先的看python针对每一个定义的类,都会计算出一个方法解析顺序(MRO)列表,MRO列表只是对所有的基类进行了简单的排序,具体如下:

    >>> print(C.__mro__)
    (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
    >>> print(type(C.__mro__))
    <class 'tuple'>

    由上面打印的内容可以看出,MRO列表是以元组的形式存储的(tuple),然后从左的子类开始查找,直到查到到最上层,无法查找为止

    MRO列表是如何确定的呢?Python采用的是c3线性化处理方式,简单的说就是满足以下三种条件:

    1)、先检查子类,在检查父类选择,

    2)、有多个父类(多重继承),按照MRO列表的顺序依次检查

    3)、如果下一个类中,出现两个合法的选择,那就继续从父类中选择(避免重复继承,保证每个父类只继承一次)

    |--super()还有一个更加神奇的用法,那就是并不直接关联父类,但是仍然可以遍历所有的父类,原因在于重新定义的方法(如下例中的:__init__)中使用了super()并且只使用了一次

    class A:
        def __init__(self):
            print("this is A")
    
    class B:
        def __init__(self):
            print('this is B')
            super().__init__()
    
    class C(B,A):
        pass
    
    c = C()
    执行结果:
    this is B
    this is A
    =======================
    class A:
        def __init__(self):
            print("this is A")
    
    class B:
        def __init__(self):
            print('this is B')
            super().__init__()
    
    class C(A,B):
        pass
    执行结果:
    this is A

    观察以上两端代码,为什么会有这样的差异化呢,第一个C(B,A)就会把A,B两个类的内容都打印出来呢?第二个C(A,B)只是把A类中的内容打印出来呢

    原因在于:super()的MRO特性,此特性在于从左的子类开始查找,当C(B,A)时,首先会查找B类,然后B类和A类由于super()的MRO(方法解析顺序)会寻找下一个方法,这样就找到了A类,并把A类中的print打印了出来;那为什么C(A,B)没有把B类中的print打印出来呢,怨原因也在于先从左边的A类开始找,结果A类并没有采用super()所以不会寻找下一个方法

    >>> print(C.__mro__)
    (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
    >>> 
    
    >>> print(C.__mro__)
    (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
    >>> 
    
    这两端代码就是以上文字说明的最好解释

     3、我们要继承的基类是动态的(有时候是A,有时候是B),我应该如何部署我的代码,以便基类可以随意改变

    答:可以先为基类定义一个别名,在类定义的时候,使用别名继承你要继承的基类,如此,当你要改变基类的时候,只需要修改给别名赋值的那个语句即可

    class BaseClass:
        def __init__(self):
            print('打印基类BaseClass')
        
    BaseAlias = BaseClass  # 为基类取别名
    
    class Derived(BaseAlias):
        def meth(self):
            BaseAlias.meth(self)  # 通过别名访问基类
    
    d = Derived()
    
    执行结果:
    打印基类BaseClass

    4、如何使用类的静态属性

    答:类中的静态属性很简单,类中直接定义的属性(没有self)就是静态属性。引用类的静态属性的方法:类名.属性名

    class C:
        count =0 #静态属性
    
        def __init__(self):
            C.count = C.count+1 #类名.属性名的形式引用
    
        def getCount(self):
            return C.count
    
    c = C()

     5、如何使用静态方法,并且说明使用过程中需要注意哪些地方

    答:静态方法是类的特殊方法,静态方法只需要在普通方法前面加上@staticmethod 修饰符即可

    class C:
        def static(arg1,arg2,arg3):
            print(arg1,arg2,arg3,arg1+arg2+arg3)
    
        def nostatic(self):
            print("I love AI")
    
    #静态方法不需要self参数,直接用类名.方法名调用。即使是使用了对象去访问,self也不会传进去      
    >>> c1.static(1,2,3)
    Traceback (most recent call last):
      File "<pyshell#8>", line 1, in <module>
        c1.static(1,2,3)
    TypeError: static() takes 3 positional arguments but 4 were given
    >>> C.static(1,2,3)
    1 2 3 6

    二、动手题

    1、定义一个类,当实例化该类的时候,自动判断传入多少个参数,并显示出来

    class C:
        def __init__(self,*args):
            if not args:
                print('并没有传入参数')
    
            else:
                print('传入了%d个参数,分别是:'%len(args),end='')
                for each in args:
                    print(each,end=' ')
    c1 = C(1,'www',20)

    2、定义一个单词Word类继承自字符串,重写比较字符串,当两个Word类对象进行比较时,根据单词的长度进行比较大小

    加分要求:实例化时如果传入的是带空格的字符串,则取第一个空格前的单词作为参数

    class Word(str):
        '''存储单词的类,定义比较单词的几种方法 '''
        def __new__(cls,word):#重载__new__方法来实现(因为str是不可变类型)
            if ' ' in word:
                word = word[:word.index(' ')]#利用切片取单词前面的空格
    
            return str.__new__(cls,word)
                
        def __gt__(self,other):#定义大于号的行为:x>y调用x.__gt__(y)
            return len(self) > len(other)
    
        def __lt__(self,other):#定义小于号的行为:x<y调用x.__lt__(y)
            return len(self)<len(other)
    
        def __ge__(self,other):#定义大于等于号的行为:x>=y调用x.__ge__(y)
            return len(self)>=len(other)
    
        def __le__(self,other):#定义小于等于号的行为:x<=y调用x.__le__(y)
            return len(self)<=len(other)

    执行结果:
    >>> c1 = Word('  word')
    >>> c2 = Word('apple')
    >>> c1<c2
    True
    >>> c1>c2
    False
    >>> c1<=c2
    True
    >>> c1>=c2
    False
    >>>
    >>> c1 = Word('  word')
    Value contains spaces. Truncating to first space.
    >>>
  • 相关阅读:
    微信开发生成带参数的二维码的讲解
    C#利用最新版的WPS实现导入导出
    【模版消息】C#推送微信模版消息(Senparc.Weixin.MP.dll)
    Photoshop的辅助线
    Newtonsoft.Json 两个Attribute含义
    VUE2.0 饿了吗视频学习笔记(二):新版本添加路由和显示Header
    VUE2.0 饿了吗视频学习笔记(一):VUE示例data.json
    Windows句柄数限制
    The CLI moved into a separate package: webpack-cli.解决办法
    Winform窗体设计工具源码
  • 原文地址:https://www.cnblogs.com/frankruby/p/9833978.html
Copyright © 2011-2022 走看看