面向对象进阶(二)----------类的内置方法

一、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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BZOJ.3265.志愿者招募加强版(费用流SPFA)

题目链接 见上题。 每类志愿者可能是若干段&#xff0c;不满足那个...全幺模矩阵(全单位模矩阵)的条件&#xff0c;所以线性规划可能存在非整数解。 于是就可以用费用流水过去顺便拿个rank2 233. //20704kb 300ms #include <queue> #include <cstdio> #include &…

谷歌相册_Google相册中的新存档功能是什么?

谷歌相册If you’re a Google Photos user, you’ve may have seen a new feature called “Archive” show up in the app’s sidebar. if not, don’t stress—it’s just now rolling out and not everyone has it yet. Since it’s new, here’s a quick look at what it i…

CenterOS 7安装Nginx

1.wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm下载对应当前系统版本的nginx包(package) 2.rpm -ivh nginx-release-centos-7-0.el7.ngx.noarch.rpm建立nginx的yum仓库 3.yum install nginx 下载并安装nginx systemctl s…

Java的组合排列问题

从4个人中选2个人参加活动&#xff0c;一共有6种选法。 从n个人中选m个人参加活动&#xff0c;一共有多少种选法&#xff1f;C(m/n)C((m-1)/(n-1))C(m/(n-1))数学算法 public class Main {public static void main(String[] args) {System.out.println("请输入总人数:&quo…

阿里云一键建站产品,阿里云自营建站-中小企业建站首选

阿里云推出的自营建站服务&#xff0c;这对于中小企业来说简直是福利了&#xff0c;现在一般的公司都开始有了自己的官网&#xff0c;有可能就是因为你的官网设计的标准&#xff0c;大气&#xff0c;客户就会对你的信任度增加&#xff0c;从而促进一笔不小的订单&#xff0c;这…

航拍拉近拉远镜头_什么是远摄镜头?

航拍拉近拉远镜头Telephoto lenses can be incredibly useful, but how is it different from other lenses, and when should you use it? 远摄镜头可能非常有用&#xff0c;但是它与其他镜头有什么不同&#xff1f;何时使用&#xff1f; 什么是远摄镜头&#xff1f; (What I…

数据库的简单了解

数据库一、什么是数据库存储数据的仓库将数据有组织&#xff0c;按照特定的格式存储在介质上叫做数据库二、比较多个数据库系统a) Oracle 最好的数据库没有之一b) SQL server 最好的数据库(windows)c) MySQL 甲骨文(Oracle) sun 开源三、SQL语言a) SQL(结构化查询语句) …

阿里云对象存储OSS支持版本管理特性

2019独角兽企业重金招聘Python工程师标准>>> 阿里云对象存储OSS现已经全面支持“对象版本管理”特性。该功能适用于所有的存储类型以及区域。当Bucket启用该特性后&#xff0c;“对象版本管理”功能可以保护和恢复误删除、误覆盖的数据。 对象存储OSS“版本管理”具…

Python第一天学习---基础语法

1.字符串的用法(String) Python 中的字符串有两种索引方式&#xff0c;从左往右以 0 开始&#xff0c;从右往左以 -1 开始。Python中的字符串不能改变。Python 没有单独的字符类型&#xff0c;一个字符就是长度为 1 的字符串这三点是我觉得Python字符处理特别的一点 我们来看第…

教你几招识别和防御Web网页木马

本文同时发表在&#xff1a;[url]http://netsecurity.51cto.com/art/200709/56360.htm[/url] 根据反病毒厂商Sophos今年的第一、第二季度报告&#xff0c;网页已经超过电子邮件成为恶意软件传播时最喜欢使用的途径&#xff0c;通过网页传播的恶意软件平均每月增加300多种。而对…

apple tv设置_如何设置Apple TV播放个人iTunes库

apple tv设置If you already have a lot of music and home videos in your iTunes library, you can easily stream it all to your Apple TV, and thus whatever output sources to which it is connected. 如果iTunes库中已经有很多音乐和家庭视频&#xff0c;则可以轻松地将…

[bzoj1050 HAOI2006] 旅行comf (kruskal)

传送门 Description 给你一个无向图&#xff0c;N(N<500)个顶点, M(M<5000)条边&#xff0c;每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T&#xff0c;求 一条路径&#xff0c;使得路径上最大边和最小边的比值最小。如果S和T之间没有路径&#xff0c;输出”IMPOSS…

好程序员技术文档HTML5开发中的javascript闭包

好程序员技术文档HTML5开发中的javascript闭包&#xff0c;事实上&#xff0c;通过使用闭包&#xff0c;我们可以做很多事情。比如模拟面向对象的代码风格;更优雅&#xff0c;更简洁的表达出代码;在某些方面提升代码的执行效率&#xff0c;同时避免对命名空间的污染&#xff0c…

亚马逊echo中国使用_如何使用亚马逊的主要照片备份所有照片

亚马逊echo中国使用Millions of people are Amazon Prime subscribers, but many of them don’t realize that in addition to free shipping and Prime Instant Video, they also get unlimited photo storage for all their computers and mobile devices. 数以百万计的人是…

抽象SQL查询:SQL-MAP技术的使用

什么是参数化查询&#xff1f;我们来看百度百科对此的定义和示例&#xff1a; 一&#xff0c;定义 ------------------------------------------------------------------ 参数化查询&#xff08;Parameterized Query 或 Parameterized Statement&#xff09;是指在设计与数据库…

EF ORM

//新增UserInfo userInfo new UserInfo();userInfo.UserName "YANG";userInfo.UserPass "123";userInfo.Email "253qq.com";userInfo.RegTime System.DateTime.Now;Model1Container db new Model1Container();db.UserInfoSet.Add(userInfo…

如何使用echo.js实现图片的懒加载(整理)

如何使用echo.js实现图片的懒加载&#xff08;整理&#xff09; 一、总结 一句话总结&#xff1a;a、在img标签中添加data-echo属性加载真实图片&#xff1a;<img class"loading" src"blank.gif" data-echo"图片真实路径" />&#xff0c;在…

还原出厂设置 擦除frp_如何备份,擦除和还原Apple Watch

还原出厂设置 擦除frpThe Apple Watch is, in its own right, a little tiny computer with data backup and security needs. Read on as we show you how to ensure your Apple Watch is backed up, wiped, and restored just like you’d do with your smartphone. Apple Wa…

exchange 2010 search mailbox 的幕后强大功能

铃……….半夜中被一阵急促的手机铃声吵醒&#xff0c;年度服务客户打来电话需要进行邮件的排查和删除工作。问其原因&#xff0c;原来是组织中有人发了一封关于领导的不健康的邮件&#xff0c;并在企业内部进行了转发&#xff0c;领导要求立即找出此类邮件并进行删除。管理员深…

Apache HBase的现状和发展

一、&#xff28;Base是什么 HBase(Hadoop Database)&#xff0c;是一个基于Google BigTable论文设计的高可靠性、高性能、可伸缩的分布式存储系统。 它有以下特征&#xff1a; 1.HBase仍然是采用行存储的&#xff0c;采用松散表的结构来获得动态列的功能&#xff1b; 2.原生海…