面向对象高阶

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)
原文地址:https://www.cnblogs.com/KbMan/p/11266861.html