zoukankan      html  css  js  c++  java
  • 面向对象高阶

    isinstance(obj, cls)、issubclass(sub, super)

    isinstance(obj, cls)

    ​ 检查对象obj是否是类cls的对象

    #例1
    class Foo(object):
        pass
    
    f = Foo()
    isinstance(f, Foo) # True
    
    #例2
    class Foo(object):
        pass
    class Bar(Foo):
        pass
    print(isinstance(Bar(), Foo))  #True
    
    f = Foo()
    b = Bar()
    type(b) == Foo  #False
    type(f) == Foo  #True
    '''
    注意:type和isinstance的区别:type(子类对象) 不会等于子类的父类,type(子类对象)会等于子类。
    isinstance(子类对象,父类) = True
    isinstance会把子类对象当做父类的一种实例
    '''
    

    issubclass(sub, super)

    检查sub类是否是super类的子类

    class Foo(object):
        pass
     
    class Bar(Foo):
        pass
     
    issubclass(Bar, Foo)
    

    类中的魔法函数

    __ str __ 和 __ repr __

    会在对象被转换为字符串时,转换的结果就是这个函数的返回值

    format_dict={
        'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
        'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
        'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
    }
    
    class School():
        def __init__(self, name, addr, type):
            self.name = name
            self.addr = addr
            self.type = type
    
        def __str__(self):  # print和str用
            return '(%s,%s)' %(self.name,self.addr)
    
        def __repr__(self): # 交互式解释器和repr()
            return 'School(%s,%s)' %(self.name,self.addr)
    
        def __format__(self, format_spec):
            if not format_spec or format_spec not in format_dict:
                format_spec = 'nat'
    
            fmt = format_dict[format_spec]
            return fmt.format(obj=self)
    
    
    s1=School('oldboy','北京','私立')
    print('from repr:', repr(s1))  # from repr: School(oldboy,北京)
    print('from str:', str(s1))  # from str: (oldboy,北京)
    print(s1) # (oldboy, 北京)
    
    print(format(s1,'nat'))  # oldboy-北京-私立
    print(format(s1,'tna'))  # 私立:oldboy:北京
    print(format(s1,'tan'))  # 私立/北京/oldboy
    print(format(s1,'asfdasdffd'))  # oldboy-北京-私立
    

    注意:str函数或者print函数,调用:obj.__ str __()

    ​ repr或者交互式解释器,调用:obj.__ repr __()

    ​ 如果 __ str __ 没有被定义, 那么就会使用 __ repr __ 来代替输出

    ​ 这两个方法的返回值必须是字符串,否则抛出异常

    class B:
    
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    
    b=B()
    print('%s'%b)  # str : class B
    print('%r'%b)  # repr : class B
    

    __ del __

    执行时机:

    ​ 1、手动删除对象时立马执行,

    ​ 2、程序结束时自动执行

    使用场景:当你的对象在使用过程中,打开了不属于解释器的资源,如:文件、网络端口

    # del使用案例
    
    class FileTool:
        """该类用于简化文件的读写操作 """
    
        def __init__(self,path):
            self.file = open(path,"rt",encoding="utf-8")
            self.a = 100
    
        def read(self):
            return self.file.read()
    
        # 在这里可以确定一个事,这个对象肯定不使用了 所以可以放心的关闭问文件了
        def __del__(self):
            self.file.close()
    
    
    tool = FileTool("a.txt")
    print(tool.read())
    
    

    __ call __

    执行时机:在调用对象时自动执行,(既对象加括号)。当 对象()时

    class A:
        def __del__(self):  #程序运行结束自动执行
            print('del run')
    
        def __call__(self, x, y):
            print('call run')
            print('x', x)
            print('y', y)
            
    a = A()
    a(1, 2)
    '''
    	call run
    	x 1
    	y 2
    	del run
    '''
    

    __ slots __

    该属性是一个类属性,用于优化对象内存占用。优化的原理:将不固定的属性,固定了。解释器就不会为这个类创建名称空间,所以__ dict __没了!

    从而达到减小开销的作用。

    类中出现了__ slots __,将导致这个类的对象无法添加新的数据属性。

    class A:
        __slots__ = ['name']
    
        def __init__(self, name):
            self.name = name
    
    a = A('小花')
    print(a.name)  # 小花
    print(a.__dict__)  # AttributeError: 'A' object has no attribute '__dict__'
    a.age = 1  # AttributeError: 'A' object has no attribute 'age'
    

    attr系列

    class Foo:
        x = 1
    
        def __init__(self, y):
            self.y = y
    
        def __getattr__(self, item):
            print('----> from getattr:你找的属性不存在')
    
        def __setattr__(self, key, value):
            print('----> from setattr')
            # self.key = value  # 这就无限递归了,你好好想想
            # self.__dict__[key] = value  # 应该使用它
    
        def __delattr__(self, item):
            print('----> from delattr')
            # del self.item  # 无限递归了
            self.__dict__.pop(item)
    
    
    f1 = Foo(10)
    
    __ getattr __

    只有在使用 点 . 调用属性且属性不存在的时候才会触发

    class A:
        x = 10
        def __getattr__(self, item):  #用.的时候且当属性不存在时触发
            print('from __getattr__:你找的属性不存在')
    
    a = A()
    print(a.x)  # 10
    a.y = 2 #这时候是调用那个__setattr__方法,__dict__ = {'y':2}
    print(a.z)  # z不存在,所以调用__getattr__方法  from __getattr__:你找的属性不存在
    print(a.__dict__)  {'y':2}
    
    __ setattr __

    添加、修改属性时会触发它的执行

    class A:
        def __setattr__(self, key, value):
            print(key)  #  a
            print(value)  #  1
            self.__dict__[key] = value  #这句话不写,对象就永远添加不了值
    
    a = A()
    a.a = 'a'
    a.a = '1'
    print(a.__dict__) # {'a':1}
    
    __ delattr __

    删除属性的时候会触发

    class A:
        def __delattr__(self, item):
            print(item)  # b
            self.__dict__.pop(item)  #如果没有这句话,删除对象属性就永远不起作用
    
    a = A()
    a.b = 'a'
    del a.b
    print(a.__dict__)  
    

    item系列

    __ setitem __

    中括号赋值时触发

    class A:
        def __setitem__(self, key, value):
            print('setitem')
            print(key) # 1
            print(value) # 2
            self.__dict__[key] = value  #添加进名称空间中
    
    a = A()
    a[1] = 2
    print(a.__dict__)
    
    __ getitem __

    中括号取值时触发

    class A:
        def __getitem__(self, item):
            print(item)  # 1
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
    a = A()
    a[1] = 2
    print(a.__dict__)  # {1:2}
    a[1] = 4
    print(a.__dict__)  # {1:4}
    
    print(a[1])  # 4
    
    __ delitem __

    中括号删除时触发

    class A:
        def __getitem__(self, item):
            print(item)
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
    
        def __delitem__(self, key):
            self.__dict__.pop(key)
    
    a = A()
    a[1] = 2
    print(a.__dict__)
    a[1] = 4
    print(a.__dict__)
    
    print(a[1])
    
    del a[1]  #触发__delitem__
    print(a.__dict__)
    

    attr/item总结

    attr:对象.属性 的实现原理

    item: 对象[属性] 的实现原理

    class AttrItem():
        def __setattr__(self, key, value): # 用对象.增加修改时,调用此方法
            self.__dict__[key] = value
    
        def __getattr__(self, item):  # 用对象.取值时,调用此方法
            return self.__dict__[item]
    
        def __delattr__(self, item):  # del 对象.属性时,调用此方法
            self.__dict__.pop(item)
    
        def __setitem__(self, key, value):  # 对象[属性],增加修改时,调用此方法
            self.__dict__[key] = value   
    
        def __getitem__(self, item):
            return self.__dict__[item]  # 对象[属性]取值时,调用此方法
        
        def __delitem__(self, key):  # del 对象[属性] 时,调用此方法 
            self.__dict__.pop(key)   
    

    运算符重载:

    当我们需要自定义对象的比较规则时,就可以在子类中覆盖 大于(__ gl __ )、等于( __ eq __ )、小于( __ lt __ ) 等方法

    注意:

    1、比较的是对象之间的的属性。重写比较方法。

    2、other指的是另一个参与比较的对象。

    3、大于和小于只要实现一个即可,符号如果不同 解释器会自动交换两个对象的位置

    class Student(object):
        def __init__(self,name,height,age):
            self.name = name
            self.height = height
            self.age = age
    
        def __gt__(self, other):
            return self.height > other.height 
        
        def __lt__(self, other):
            return self.height < other.height
    
        def __eq__(self, other):
            if self.name == other.name and  self.age == other.age and self.height == other.height:
                return True
            return False
    
    stu1 = Student("jack",180,28)
    stu2 = Student("jack",180,28)
    # print(stu1 < stu2)
    print(stu1 == stu2)
    

    迭代器协议

    '''
    迭代器是指具有__iter__和__next__的对象
    我们可以为对象增加这两个方法来让对象变成一个迭代器 
    '''
    class MyRange:
    
        def __init__(self,start,end,step):
            self.start = start
            self.end = end
            self.step = step
    
        def __iter__(self): #调用__iter__ 要返回的对象就是迭代器
            return self
    
        def __next__(self):
            a = self.start
            self.start += self.step
            if a < self.end:
                return a
            else:
                raise StopIteration  # for循环每循环一次,就调用一次__next__,结束时要返回一个抛出异常让for循环接收。
                
    for i in MyRange(1,10,2):
        print(i)
    
  • 相关阅读:
    《软件工艺》-初评
    UI设计心得(1)
    理想生活应该是...
    OpenPOP.NET+OpenSMTP.NET=?最强.NET开源邮件组件 Mail.NET!
    Outlook应用开发(3)之插件引擎
    最近发现的几个酷.net代码
    买了几本新书,推荐一下
    一个游标简单例子
    winform中捕获程序未处理的所有异常
    DataTable的Merge方法和添加datatable到dataset
  • 原文地址:https://www.cnblogs.com/KbMan/p/11266861.html
Copyright © 2011-2022 走看看