[python]面向对象高级
目录
- 一 isinstance(obj,cls)和issubclass(sub,super)
- 二 反射
- 三 __setattr__,__delattr__,__getattr__
- 四 二次加工标准类型(包装)
- 五 __getattribute__
- 六 描述符(__get__,__set__,__delete__)
- 六 property
- 七 __setitem__,__getitem,__delitem__
- 八 __str__,__repr__,__format__
- 九 __slots__
- 十 __next__和__iter__实现迭代器协议
- 十一 __doc__
- 十二 __module__和__class__
- 十三 __del__
- 十四 __enter__和__exit__
- 十五 __call__
- mro
- super
- 类.__init__(self,参数)
- super(类,self).__init__(参数)
- super().__init__(参数) python3推荐,python2中未提供此方法
一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
1 class Foo(object): 2 pass 3 4 obj = Foo() 5 6 isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
1 class Foo(object): 2 pass 3 4 class Bar(Foo): 5 pass 6 7 issubclass(Bar, Foo)
二 反射
什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
hasattr(object,name)# 判断object中有没有一个name字符串对应的方法或属性getattr(object, name, default=None)setattr(x, y, v)delattr(x, y)
类也是对象
class Foo(object):staticField = "old boy"def __init__(self):self.name = 'wupeiqi'def func(self):return 'func'@staticmethoddef bar():return 'bar'print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')
反射当前模块
#!/usr/bin/env python # -*- coding:utf-8 -*-import sysdef s1():print 's1'def s2():print 's2'this_module = sys.modules[__name__]hasattr(this_module, 's1') getattr(this_module, 's2')
三 setattr,delattr,getattr
class Foo:x=1def __init__(self,y):self.y=ydef __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)#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
四 二次加工标准类型(包装)
包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)
class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和middef append(self, p_object):' 派生自己的append:加上类型检查'if not isinstance(p_object,int):raise TypeError('must be int')super().append(p_object)@propertydef mid(self):'新增自己的属性'index=len(self)//2return self[index]l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型print(l.mid)#其余的方法都继承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
import time
class FileHandle:def __init__(self,filename,mode='r',encoding='utf-8'):self.file=open(filename,mode,encoding=encoding)def write(self,line):t=time.strftime('%Y-%m-%d %T')self.file.write('%s %s' %(t,line))def __getattr__(self, item):return getattr(self.file,item)f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()
五 getattribute
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'class Foo:def __init__(self,x):self.x=xdef __getattr__(self, item):print('执行的是我')# return self.__dict__[item]def __getattribute__(self, item):print('不管是否存在,我都会执行')raise AttributeError('哈哈')f1=Foo(10)
f1.x
f1.xxxxxx#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError
六 描述符(get,set,delete)
描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),set(),delete()中的一个,这也被称为描述符协议
get():调用一个属性时,触发
set():为一个属性赋值时,触发
delete():采用del删除属性时,触发
class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符def __get__(self, instance, owner):passdef __set__(self, instance, value):passdef __delete__(self, instance):pass
六 property
一个静态属性property本质就是实现了get,set,delete三种方法
class Foo:@propertydef AAA(self):print('get的时候运行我啊')@AAA.setterdef AAA(self,value):print('set的时候运行我啊')@AAA.deleterdef AAA(self):print('delete的时候运行我啊')#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
或
class Foo:def get_AAA(self):print('get的时候运行我啊')def set_AAA(self,value):print('set的时候运行我啊')def delete_AAA(self):print('delete的时候运行我啊')AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
七 setitem,__getitem,delitem
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__)
八 str,repr,format
改变对象的字符串显示__str__,repr
自定制格式化字符串__format__
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
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=nameself.addr=addrself.type=typedef __repr__(self):return 'School(%s,%s)' %(self.name,self.addr)def __str__(self):return '(%s,%s)' %(self.name,self.addr)def __format__(self, format_spec):# if format_specif 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('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
九 slots
'''
1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给
实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该
只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具。'''
class Foo:__slots__='x'f1=Foo()
f1.x=1
f1.y=2#报错
print(f1.__slots__) #f1不再有__dict__class Bar:__slots__=['x','y']n=Bar()
n.x,n.y=1,2
n.z=3#报错
十 __next__和__iter__实现迭代器协议
class Foo:def __init__(self,start,stop):self.num=startself.stop=stopdef __iter__(self):return selfdef __next__(self):if self.num >= self.stop:raise StopIterationn=self.numself.num+=1return nf=Foo(1,5)
from collections import Iterable,Iterator
print(isinstance(f,Iterator))for i in Foo(1,5):print(i)
十一 doc
class Foo:'我是描述信息'passclass Bar(Foo):pass
print(Bar.__doc__) #该属性无法继承给子类
十二 module__和__class
module 表示当前操作的对象在那个模块
class 表示当前操作的对象的类是什么
#!/usr/bin/env python
# -*- coding:utf-8 -*-class C:def __init__(self):self.name = ‘SB'from lib.aa import Cobj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类
十三 del
析构方法,当对象在内存中被释放时,自动触发执行。
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__
class Foo:def __del__(self):print('执行我啦')f1=Foo()
del f1
print('------->')#输出结果
执行我啦
------->
十四 enter__和__exit
下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
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中代码块执行完毕时执行我啊')with Open('a.txt') as f:print('=====>执行代码块')# print(f,f.name)
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中代码块执行完毕时执行我啊')print(exc_type)print(exc_val)print(exc_tb)with Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->不会执行
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,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中代码块执行完毕时执行我啊')print(exc_type)print(exc_val)print(exc_tb)return Truewith Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->会执行
用途或者说好处:
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__
mro
每定义一个类,python会计算出方法解析顺序列表(mro),调用方法:类.mro()
class A:passclass B:pass# [<class '__main__.B'>, <class 'object'>]
print(B.mro())
super
类.init(self,参数)
class A:def __init__(self, name):self.name = nameclass B(A):def __init__(self, name):A.__init__(self, name)# [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
print(B.mro())
# B
print(B("B").name)
super(类,self).init(参数)
class A:def __init__(self, name):self.name = nameclass B(A):def __init__(self, name):super(B, self).__init__(name)print(B.mro())
print(B("B").name)
super().init(参数) python3推荐,python2中未提供此方法
class A:def __init__(self, name):self.name = nameclass B(A):def __init__(self, name):super().__init__(name)print(B.mro())
print(B("B").name)
[python]面向对象高级相关推荐
- python 面向对象高级
08 面向对象高级 常用内置函数 #hasattr() 判断实例对象属性是否存在 hasattr(aa,'abc') #存在返回True,不存在返回False #getattr() 返回实例对象属性值 ...
- python 面向对象高级应用(三)
目录: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__getattr__ 二次加工标准类型(包装) __ ...
- python类高级用法_十.python面向对象高级用法
1.反射 1.1 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的 ...
- python面向对象高级
__str__,__repr__ __str__定义在类内部,必须返回一个字符串类型 __repr__定义在类内部,必须返回一个字符串类型 打印由这个类产生的对象时,会触发执行__str__,如果没有 ...
- Python 面向对象高级编程——定制类
1.1 定制类 1.1.1 __str__ >>> class Student(object): ... def __init__(self, name): ... ...
- Python面向对象高级编程
1.__slots__ 通过Types包中的MethodType将外部方法与类对象进行绑定(该方法只能对绑定的对象生效) """a test module"&q ...
- Python学习笔记:面向对象高级编程(完)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:面向对象高级编程(中下)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:面向对象高级编程(中上)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
最新文章
- Caffe2——cifar10数据集创建lmdb或leveldb类型的数据
- 清华大学研究称国内多城市饮用水含高浓度PFAS
- redis set 超时_Redis 更新(set) key值过期时间被重置
- python urllib2_Python爬虫 urllib2的使用方法详解
- Ubuntu mysql连接错误10060/10061的方法
- 敏捷管理之绩效考核方案
- diff算法_详解 React 16 的 Diff 策略
- python数据分析_使用Python进行数据分析
- 让网站变成灰色插件 可以设定特殊时间
- 陈正康考研英语长难句 51~75
- python调用flask接口实例化_常用业务接口界面化 in python flask
- matlab 灰度图像矩阵,MatLab矩阵运算——图像灰度化
- goeasy java_Java GoEasy 实现服务端推送和Web端推送
- payjs 源码_ZFAKA发卡系统用宝塔安装详细图文教程+对接Payjs个人支付版本
- 计算机程序停止工作怎么办,如何将“某某程序已正常停止工作,请关闭程序”这个提示自动关闭...
- 微信的那个老外产品经理,又写了一篇《中国移动应用设计趋势》
- layui模板语言,渲染表格分组合并行
- dayjs格式化使用
- Guide哥|我写了四年博客,收获了20w+读者。我为什么推荐你写博客?
- 医疗器械网络安全漏洞自评报告模板
热门文章
- c#实现魔兽(warIII)中显血和改键功能 (附源码)(Hook中start方法已改进)
- 学习笔记:医学图像配准简介—附voxelmorph模型
- 【拧巴拧巴就20了】【随笔】我在大学为什么要学这个?
- 2022 重新认识绩效评估:定义、特点、步骤【下篇】
- 关于水表指针的简单识别(提供一个小思路,带源码)
- 大宗交易数据挖掘(四)
- 济南商标驳回复审流程及时间
- Ming-Hsuan Yang: Publications
- 27:NET5 AOP-Filter扩展定制
- 巨微MG126低功耗蓝牙芯片实现物联网系统设计