面向对象进阶(二)----------类的内置方法
一、isinstance(obj,cls)和issubclass(sub,super)
1. isinstance(obj,cls): 检查是否obj是否是类 cls 的对象
class Player:passp = Player()print(isinstance(p, Player))>>> Ture
2. issubclass(sub, super): 检查sub类是否是 super 类的派生类
class Player:passclass Basketball(Player):passprint(issubclass(Basketball, Player))>>> Ture
二、__getattribute__
1. 回顾__getattr__方法
class Player:x = 23y = 6def __init__(self):passdef __getattr__(self, item):print('不存在%s属性' % item)p = Player() p.x p.xy>>> 不存在xy属性
2. __getattribute__方法演示
class Player:x = 23y = 6def __init__(self):passdef __getattribute__(self, item):print('存不存在该属性都会触发__getattribute__方法')p = Player() p.x p.xy>>> 存不存在该属性都会触发__getattribute__方法
3. __getattr__与__getattribute__同时存在时
class Foo:def __init__(self, x):self.x = xdef __getattr__(self, item):print('执行的是__getattr__')# return self.__dict__[item]def __getattribute__(self, item):print('不管是否存在,__getattribute都会执行')raise AttributeError('抛出一个错误')f1=Foo(10) f1.x f1.xxxxxx>>> 不管是否存在,__getattribute都会执行#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__, 若__getattribute__在执行过程中抛出异常AttributeError, 则先执行__getattribute__,然后执行__getattr__
三、__setitem__, __getitem, __delitem__
1. __setitem__, __getitem__, __delitem__都是 obj[‘属性’]的方式去操作属性时触发的方法
__getitem__:obj['属性'] 时触发
__setitem__:obj['属性']=属性的值 时触发
__delitem__:del obj['属性'] 时触发
2.与__getattr__, __setattr__, __delattr__的同和异
同:赋值的底层原理都一样
f1.name = 'lebron' #做的就是往属性字典里添加或覆盖值 原理:----->__setattr__----->f1.__dict__['name'] = 'lebron'f1['name'] = 'lebron' 原理:----->__setitem__----->f1.__dict__['name'] = 'lebron'#两个方法的底层都是一样的,只不过通过__setattr__,__setitem__中转了一下
异:
__getattr__,__setattr__,__delattr__
obj点的方式去操作属性时触发的方法
__getitem__,__setitem_,__delitem__
obj[‘属性’]的方式去操作属性时触发的方法
__getattr__:obj.属性不存在时触发
__setattr__:obj.属性=属性的值 时触发
__delattr__:del obj.属性 时触发
__getitem__:obj['属性'] 时触发
__setitem__:obj['属性']=属性的值 时触发
__delitem__:del obj['属性'] 时触发
class Foo:def __init__(self,name):self.name=namedef __getitem__(self, item):print(self.__dict__[item])def __setitem__(self, key, value):self.__dict__[key]=valuedef __delitem__(self, key):print('del obj[key]时,我执行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key时,我执行')self.__dict__.pop(item)f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__) >>>
del obj.key时,我执行
del obj[key]时,我执行
{'name': 'alex'}
四、__str__, __repr__
__str__: 控制返回值,并且返回值必须是str类型,否则报错
__repr__:控制返回值并且返回值必须是str类型,否则报错
__repr__是__str__的替代品,如果__str__存在,直接按__str__的返回值,返回信息,不会执行__repr__,如果不存在,会执行__repr__,并得到__repr__的返回值
li = list('12345') print(type(li)) def foo():pass print(type(foo)) >>> <class 'list'> <class 'function'>#调用了类内部的__str__方法,从而打印出<class 'list'>, <class 'function'>
class Foo:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return '名字是%s,年龄是%s' %(self.name, self.age)def __str__(self):return 'name is %s, age is %s' %(self.name, self.age) p1 = Foo('chen', '23') print(p1)>>> name is chen, age is 23#__str__和__repr__都存在时,只会执行__str__方法
五、自定制格式化字符串__format__
format_dic = {'ymd':'{0.year}{0.mon}{0.day}','y:m:d':'{0.year}:{0.mon}:{0.day}','y-m-d':'{0.year}-{0.mon}-{0.day}' } class Date:def __init__(self, year, mon, day):self.year = yearself.mon = monself.day = daydef __format__(self, format_spec):if not format_spec or format_spec not in format_dic: #用户输入的格式不存在时,使用默认的格式format_spec = 'y:m:d'return format_dic[format_spec].format(self) d = Date('2019','04','01') print(d.__format__('y-m-d')) print(d.__format__('y:m:d')) print(d.__format__('ymd')) print(d.__format__('asdf'))>>> 2019-04-01 2019:04:01 20190401 2019:04:01
六、__slots__
1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性) 2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的) 3.为何使用__slots__: 字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外, 定义了__slots__后的类不再支持一些普通类特性了,比如多继承。大多数情况下,你应该只在那些经常别使用的用作数据结构的类上定义
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具。
class Foo:__slots__ = ['name', 'age'] #__dict__ = {'name': None, 'age': None} p = Foo() p.name = 'chen' p.age = '18' #print(p.__dict__) 报错, __slots__方法下,实例化对象不存在属性字典 #p.height = '1.8' 报错,__slots__方法下,实例化对象只能设置指定的属性
七、__doc__
类的描述信息
class Foo: '我是描述信息' pass print(Foo.__doc__)>>>'我是描述信息'
该属性无法被继承
class Foo:'我是描述信息'passclass Bar(Foo):pass print(Bar.__doc__) #该属性无法继承给子类>>> None
八、 __module__和__class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
from test import Playerp = Player('lebron_james', 34, '2.03m')print(p.__module__) print(p.__class__)>>> test #输出模块名 <class 'test.Player'> #输出对象的类名
九、__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__, 如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__
1. 简单示范
class Foo:def __del__(self):print('执行我啦')f1=Foo() del f1 print('------->')>>> 执行我啦 #删除f1对象,触发__del__方法 ------->class Foo:def __del__(self):print('执行我啦')f1=Foo() print('------->')>>> -------> 执行我啦 #程序执行完毕,释放f1对象内存,触发__del__方法
2. 典型的应用场景:
创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中。
当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源
这与文件处理是一个道理:
f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件 del f #只回收用户空间的f,操作系统的文件还处于打开状态#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是 f=open('a.txt') 读写... f.close() 很多情况下大家都容易忽略f.close,这就用到了with上下文管理
十、__enter__和__exit__
我们知道在操作文件对象的时候可以这么写
with open('a.txt') as f:'代码块'
上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法。
1.上下文管理协议
class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')return selfdef __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时执行__exit__')with Open('a.txt') as f:print('=====>执行代码块')print(f,f.name)>>> 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量 =====>执行代码块 <__main__.Open object at 0x0000013191B98710> a.txt with中代码块执行完毕时执行__exit__
2. __exit__()中的三个参数分别代表 异常类型,异常值 和 追溯信息,with语句中代码块出现异常,则with后的代码都无法执行。
class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时执行__exit__')print(exc_type)print(exc_val)print(exc_tb)with Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***') print('0'*100) # ------------------------------->不会执行
3. 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with中的代码将不会继续执行,而with后的语句正常执行。
class Open:def __init__(self, name):self.name = namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时__exit__')print(exc_type)print(exc_val)print(exc_tb)return Truewith Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***') print('0'*100) #------------------------------->会执行
4.模拟open
class Open():def __init__(self, filename, mode='r', encoding='utf-8'):self.file = open(filename, mode, encoding=encoding)def __enter__(self):return self.filedef __exit__(self, exc_type, exc_val, exc_tb):self.file.close()return Truedef __getattr__(self, item):return getattr(self.file, item)with Open('a.txt','w') as f:print(f)f.write('aaaaaa')f.wasdf #抛出异常,交给__exit__处理
5. 总结:
with obj as f:'代码块'1. with obj -----> 触发obj.__enter__(), 拿到返回值2. as f -----> f = 返回值3.with obj as f 等同于 f = obj.__enter__()4. 执行代码块 一:没有异常的情况下,整个代码块运行完毕后去触发__exit__(),它的三个参数都为空 二:有异常的情况下,从异常出先的位置直接触发__exit__a:如果__exit__()返回值为Ture,代表吞掉了异常,with中的代码终止运行, with后的代码正常运行b:如果__exit__()的返回值不为Ture,代表吐出了异常c:__exit__的运行完毕就代表了整个with语句的执行完毕
6. 用途或者说好处:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预。
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处。
十一、__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()
class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):print('__call__')obj = Foo() # 执行 __init__ obj() # 执行 __call__
十二、__next__和__iter__实现迭代器协议
1. 简单示范
class Foo:def __init__(self, x):self.x = xdef __iter__(self):return selfdef __next__(self):self.x += 1if self.x > 6:raise StopIterationreturn self.xf = Foo(3)for i in f:print(i)
2. 练习:简单模拟range,加上步长
class Range:def __init__(self, start, end, step):self.start = startself.end = endself.step = stepdef __iter__(self):return selfdef __next__(self):self.start += self.stepif self.start > self.end:raise StopIterationreturn self.startr = Range(1,10,2)for i in r:print(i)>>> 3 5 7 9
3. 实现斐波那契数列
class Fib:def __init__(self):self.a = 1self.b = 1def __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > 15:raise StopIterationreturn self.af = Fib()for i in f:print(i)
转载于:https://www.cnblogs.com/cjsword/p/10642041.html
面向对象进阶(二)----------类的内置方法相关推荐
- 面向对象之反射和其他内置方法
一.反射 1.概念:主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.简而言之,就是自身调用自身即可实现已定义的某一功能,以达到简化程序的作用. 2.python面向对象中的反射是指通过字符 ...
- python __repr__方法_第8.13节 Python类中内置方法__repr__详解
当我们在交互环境下输入对象时会直接显示对象的信息,交互环境下输入print(对象)或代码中print(对象)也会输出对象的信息,这些输出信息与两个内置方法:__str__方法和__repr__方法有关 ...
- 类的属性、类的方法、类的内置方法
类的属性 变量在类中称为类的属性,函数在类中称为类的方法,类的属性分为以下几种: (1) 公有属性:在类中和类外都能调用的属性,定义的时候与变量的定义一致,如 color = 'yellow' (2) ...
- python 类的内置方法_Python 类的常用内置方法
类的内置方法(魔法方法): 凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,类的内置方法,会在满足某种条件下自动触发. 1.1__new__ __new__:在___init__触发前, ...
- python类的内置方法_python面向对象之类中的内置方法
__setattr__,__delattr__,__getattr__,__getattribute__以及标准类型的二次加工 __setattr__,__delattr__,__getattr__的 ...
- python 类的内置方法_【转】[python] 类常用的内置方法
原文:http://xukaizijian.blog.163.com/blog/static/170433119201111894228877/ 内置方法 说明 __init__(self,...) ...
- python 面向对象 类的内置方法
判断是不是类cls的对象 class A:passa = A() print(isinstance(a,A)) 判断类sub是不是super的子类 class A:passclass B(A):pas ...
- 类的内置方法__attr__介绍
1.hasattr getaddr setaddr delattr 这四个函数同样也适用于类 class BlackMedium:feture="Ugly"def __init ...
- 反射(高大上)、类的内置方法
反射 对象的反射 类的反射 模块的反射 本模块的反射:找到本模块sys.modules[__name__] python面向对象中的反射:通过字符串的形式操作对象相关的属性.python中的一切事物都 ...
最新文章
- Sun Solaris 9 下Squid 代理服务器的配置笔记
- 用ESP32怎么实现离线语音
- SecurityManager安全管理器
- 读书二十二载,信念很简单,把书念下去,然后走出去,不枉活一世。
- LeetCode 88 合并两个有序数组
- git pull keeping local changes
- ElementUI-学生管理系统后台实例
- 「管理数学基础」3.3 凸分析:凸函数的极值和凸规划
- servlet之监听器
- EBS之JTF_Grid 开发总结
- 家里的无线网和优酷服务器,告诉你一个可以让家里无线网变快的方法
- Java 处理资源的try语句 (try-with-resources, TWR)
- 解决启动IIS发生意外错误 0x8ffe2740
- 数据结构循环队列C++实现
- 这苦日子B站熬出头了?
- 聊下Android的专利许可和商标
- 78㎡网络机房动环监控及告警方案
- 北京大学肖臻老师《区块链技术与应用》ETH笔记 - 5.0 ETH中GHOST协议篇
- 几何校正(image to image)
- Ionic3项目实战
热门文章
- vue 滑动置顶功能_VUE 实现滚动监听 导航栏置顶的方法_蜡烛_前端开发者
- csv导入mysql linux_如何将CSV文件导入MySQL表
- 我用代码来给你们分析一个赚钱的技巧
- 渗透测试入门DVWA 教程1:环境搭建
- HDU 5037 Frog(2014年北京网络赛 F 贪心)
- windows 下安装wamp环境
- 图片处理--熔铸特效
- [信息收集] HCOMP 2010概况及收录论文
- 奥巴马访华:不建议过度审查 提倡加强互联网开放
- ***一般如何***服务器