一.多态
多态:一种事物具备多种不同的形态
多态性:具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。
多态的好处:降低使用难度
class chicken: def bark(self): print('窝窝') def spawn(self): print('wowowo') class duck: def bark(self): print('gaga') def spawn(self): print('下鸭蛋') class goose: def bark(self): print('ga~ga') def spawn(self): print('下e蛋') def manage(obj) : obj.bark() obj.spawn() j = chicken() d = duck() g = goose() manage(j) manage(d) manage(g)
多态的实现方式:
接口,抽象类,鸭子类型
二.进阶方法
1.__isinstance__与__issubclass __
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class foo: pass obj = foo() abc = 123 print(isinstance(obj,foo)) print(isinstance(abc,foo))
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo))
2.__str__与__repr__
__str__打印的时候自动触发,,如果不返回字符串类型,则会报错
class Foo: def __init__(self, name, age): """对象实例化的时候自动触发""" self.name = name self.age = age def __str__(self): print('打印的时候自动触发,但是其实不需要print即可打印') return f'{self.name}:{self.age}' # 如果不返回字符串类型,则会报错 obj = Foo('nick', 18) # obj.__str__() print(obj)
__repr__ 如果__str__没有被定义,那么就会使用__repr__来代替输出
class School: def __init__(self, name, addr, type): self.name = name self.addr = addr self.type = type def __repr__(self): return 'School(%s,%s)' % (self.name, self.addr) def __str__(self): return '(%s,%s)' % (self.name, self.addr) s1 = School('oldboy1', '北京', '私立') # print('from repr: ', repr(s1)) # print('from str: ', str(s1)) print(s1)
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
注意:这俩方法的返回值必须是字符串,否则抛出异常
3.__del__与__call__
__del__ 析构方法(函数),当对象在内存中被释放时,自动触发执行。
class Foo: def __del__(self): print('执行我啦') f1=Foo() f2 = Foo() del f1 print('------->') # 执行时机: 手动删除对象时立马执行,或是程序运行结束时也会自动执行 # 使用场景: 可以手动回收系统相关资源
__call__ 对象后面加括号,触发执行。
# call 对象后面加括号,触发执行。 # 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ; # 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__ Foo()()
4.__slots__
__slots__ 的功能:节省内存(固定对象的内存大小) 防止用户给实例增加新的属性
import sys class Person: __slots__ = ["name"] def __init__(self,name): self.name = name p = Person("jck") # 查看内存占用 print(sys.getsizeof(p)) p.name = 20 # 无法添加 # 使用__slots__以后__dict没有了__ print(p.__dict__)
5.__getattr__ __setattr__ 和 __delattr__
getattr 用点访问属性的时如果属性不存在时执行
setattr 用点设置属性时
delattr 用del 对象.属性 删除属性时 执行
getattribute 该函数也是用来获取属性
获取属性则先执行getattribute函数,如果没有拿到属性则继续调用 getattr函数,如果拿到了则直接返回
class A: def __setattr__(self, key, value): print(key,value) super().__setattr__(key,value) # self.__dict__ # def __delattr__(self, item): print("__delattr__") print(item) super().__delattr__(item) def __getattr__(self, item): print("__getattr__") return 1 def __getattribute__(self, item): print("__getattribute__") return super().__getattribute__(item) # a = A() a.name = "xxx" print(a.name) del a.name print(a.name)
6.__getitem__ __setitem__ 和 __delitem__
getitem 当你用中括号去获取属性时 执行
setitem 当你用中括号去设置属性时 执行
delitem 当你用中括号去删除属性时 执行
class A: def __getitem__(self, item): print("__getitem__") return self.__dict__[item] def __setitem__(self, key, value): print("__setitem__") self.__dict__[key] = value def __delitem__(self, key): del self.__dict__[key] print("__delitem__") a = A() # a.name = "jack" a["name"] = "jack" print(a["name"]) del a["name"] print(a["name"])
三.运算符重载
在我们使用抽象字符时,python解释器会按照符号规定的含义,调用对应的处理函数,。
在我们需要自定义对象的比较规则时,就可在子类中覆盖 大于(gt) 等于(eq) 小于(lt)等一系列方法....
class Student(object): def __init__(self, name, height, age): self.name = name self.height = height self.age = age def __gt__(self, other): # print(self) # print(other) # print("__gt__") 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", 167, 28) print(stu1 < stu2) 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): return self def __next__(self): a = self.start self.start += self.step if a < self.end: return a else: raise StopIteration for i in MyRange(1,10,2): print(i)
五.上下文管理
上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
class MyOpen(object): def __init__(self,path): self.path = path def __enter__(self): self.file = open(self.path) print("enter.....") return self.file def __exit__(self, exc_type, exc_val, exc_tb): # __exit__()中的三个参数分别代表异常类型,异常值和追溯信息 print("exit...") print(exc_type,exc_val,exc_tb) self.file.close() # return True return False #exit函数 可以有一个bool类型返回值,True表示异常被抛出 # False,异常未被处理。若上下文中出现异常,程序会被中断报错 with MyOpen("a.txt") as m: #出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量 print(m) print(m.read()) # "123"+1 #当代码执行完毕后执行exit, 或者遇到异常会立即执行exit, 并传入错误信息
优点:
-
把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
-
在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制