python之面向对象的高级进阶
一 、isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
- class Foo(object):
- pass
- obj = Foo()
- isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
- class Foo(object):
- pass
- class Bar(Foo):
- pass
- issubclass(Bar, Foo)
二 反射
1 什么是反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
三 __setattr__,__delattr__,__getattr__
- 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)
- #__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
- 三者的用法演示
四 二次加工标准类型(包装)
- class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
- def append(self, p_object):
- ' 派生自己的append:加上类型检查'
- if not isinstance(p_object,int):
- raise TypeError('must be int')
- super().append(p_object)
- @property
- def mid(self):
- '新增自己的属性'
- index=len(self)//2
- return 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)
- 二次加工标准类型(基于继承实现)
五 __getattribute__
- class Foo:
- def __init__(self,x):
- self.x=x
- def __getattr__(self, item):
- print('执行的是我')
- # return self.__dict__[item]
- f1=Foo(10)
- print(f1.x)
- f1.xxxxxx #不存在的属性访问,触发__getattr__
- 回顾__getattr__
- class Foo:
- def __init__(self,x):
- self.x=x
- def __getattribute__(self, item):
- print('不管是否存在,我都会执行')
- f1=Foo(10)
- f1.x
- f1.xxxxxx
- __getattribute__
- #_*_coding:utf-8_*_
- __author__ = 'Linhaifeng'
- class Foo:
- def __init__(self,x):
- self.x=x
- def __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):
- pass
- def __set__(self, instance, value):
- pass
- def __delete__(self, instance):
- pass
- 定义一个描述符
2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
- class Foo:
- def __get__(self, instance, owner):
- print('触发get')
- def __set__(self, instance, value):
- print('触发set')
- def __delete__(self, instance):
- print('触发delete')
- #包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法
- f1=Foo()
- f1.name='egon'
- f1.name
- del f1.name
- #疑问:何时,何地,会触发这三个方法的执行
- 引子:描述符类产生的实例进行属性操作并不会触发三个方法的执行
- #描述符Str
- class Str:
- def __get__(self, instance, owner):
- print('Str调用')
- def __set__(self, instance, value):
- print('Str设置...')
- def __delete__(self, instance):
- print('Str删除...')
- #描述符Int
- class Int:
- def __get__(self, instance, owner):
- print('Int调用')
- def __set__(self, instance, value):
- print('Int设置...')
- def __delete__(self, instance):
- print('Int删除...')
- class People:
- name=Str()
- age=Int()
- def __init__(self,name,age): #name被Str类代理,age被Int类代理,
- self.name=name
- self.age=age
- #何地?:定义成另外一个类的类属性
- #何时?:且看下列演示
- p1=People('alex',18)
- #描述符Str的使用
- p1.name
- p1.name='egon'
- del p1.name
- #描述符Int的使用
- p1.age
- p1.age=18
- del p1.age
- #我们来瞅瞅到底发生了什么
- print(p1.__dict__)
- print(People.__dict__)
- #补充
- print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
- print(type(p1).__dict__ == People.__dict__)
- 描述符应用之何时?何地?
3 描述符分两种
一 数据描述符:至少实现了__get__()和__set__()
- class Foo:
- def __set__(self, instance, value):
- print('set')
- def __get__(self, instance, owner):
- print('get')
二 非数据描述符:没有实现__set__()
- class Foo:
- def __get__(self, instance, owner):
- print('get')
4 注意事项:
一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
六 再看property
一个静态属性property本质就是实现了get,set,delete三种方法
- class Foo:
- @property
- def AAA(self):
- print('get的时候运行我啊')
- @AAA.setter
- def AAA(self,value):
- print('set的时候运行我啊')
- @AAA.deleter
- def 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=name
- def __getitem__(self, item):
- print(self.__dict__[item])
- def __setitem__(self, key, value):
- self.__dict__[key]=value
- def __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=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)
- def __format__(self, format_spec):
- # if 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('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#报错
- __slots__使用
- class Foo:
- __slots__=['name','age']
- f1=Foo()
- f1.name='alex'
- f1.age=18
- print(f1.__slots__)
- f2=Foo()
- f2.name='egon'
- f2.age=19
- print(f2.__slots__)
- print(Foo.__dict__)
- #f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存
- 刨根问底
十 __next__和__iter__实现迭代器协议
- #_*_coding:utf-8_*_
- __author__ = 'Linhaifeng'
- class Foo:
- def __init__(self,x):
- self.x=x
- def __iter__(self):
- return self
- def __next__(self):
- n=self.x
- self.x+=1
- return self.x
- f=Foo(3)
- for i in f:
- print(i)
- 简单示范
- class Foo:
- def __init__(self,start,stop):
- self.num=start
- self.stop=stop
- def __iter__(self):
- return self
- def __next__(self):
- if self.num >= self.stop:
- raise StopIteration
- n=self.num
- self.num+=1
- return n
- f=Foo(1,5)
- from collections import Iterable,Iterator
- print(isinstance(f,Iterator))
- for i in Foo(1,5):
- print(i)
十一 __doc__
- class Foo:
- '我是描述信息'
- pass
- print(Foo.__doc__)
- class Foo:
- '我是描述信息'
- pass
- class 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'
- lib/aa.py
- from lib.aa import C
- obj = C()
- print obj.__module__ # 输出 lib.aa,即:输出模块
- print obj.__class__ # 输出 lib.aa.C,即:输出类
十三 __del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__
python之面向对象的高级进阶的更多相关文章
- Python中面向对象初识到进阶
面向对象初识到进阶 # 面向对象结构: # class 类名: # def __init__(self,参数1,参数2): # self.对象的属性1 = 参数1 # self.对象的属性2 = 参数 ...
- Python(面向对象5——高级)
面向对象进阶 一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 class Fo ...
- python基础——面向对象进阶下
python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...
- python基础——面向对象进阶
python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...
- Python面向对象编程高级特性
***这里还是根据网上资料,主要是廖雪峰老师的教程学习的笔记,主要介绍python面向对象的高级特性,笔记不全,只是记录自己觉得容易出错的地方*** 1.python作为一种动态语言,他的动态绑定机制 ...
- Python 3 面向对象进阶
Python 3 面向对象进阶 一. isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的 ...
- 一凡老师亲录视频,Python从零基础到高级进阶带你飞
如需Q群交流 群:893694563 不定时更新2-3节视频 零基础学生请点击 Python基础入门视频 如果你刚初入测试行业 如果你刚转入到测试行业 如果你想学习Python,学习自动化,搭建自动化 ...
- Python 高级进阶知识(一)
参考 Python学习手册 第四版 1 from vs import import 模块 : 导入的一整个模块(python中模块对应一个py文件) 因为import使用一个变量名引用整个模块对象,所 ...
- 最新Python3.6从入门到高级进阶实战视频教程
点击了解更多Python课程>>> 最新Python3.6从入门到高级进阶实战视频教程 第1篇 Python入门导学 第2篇 Python环境装置 第3篇 了解什么是写代码与Pyth ...
随机推荐
- cocos2d JS-(JavaScript) 动态生成方法的例子
function User(properties) { for (var i in properties) { (function (which) { var p = i; which["g ...
- Selenium基础知识(八)文本域处理textarea
textarea文本域selenium有时处理不了,但是我们可以采用迂回,解决这个问题 那么,我们用到了execute_script()方法来调用javascript来解决这个问题 这其中涉及DOM, ...
- 测试一体机ASM Disk online操作
环境:3台虚拟机 RHEL 7.3 + Oracle RAC 11.2.0.4 问题现象:RAC运行正常,ASM磁盘组Normal冗余,节点主机重启,offline状态的asm disk短时间内可以直 ...
- 基于AOP注解实现业务功能的动态配置
一.导入jar包 <dependency><!-- 4.引入AOP--> <groupId>org.springframework.boot</groupId ...
- Python之装饰器的实例
1.1装饰器的应用:参数类型检查 函数参数的检查,一定是在函数外 函数应该作为参数,传入到检查函数中 检查函数拿到函数传入的实际参数,与形参声明对比 __annotations__属性是一个字典,其中 ...
- html5-figure和figcaption元素
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Visible Lattice Points (莫比乌斯反演)
Visible Lattice Points 题意 : 从(0,0,0)出发在(N,N,N)范围内有多少条不从重合的直线:我们只要求gcd(x,y,z) = 1; 的点有多少个就可以了: 比如 : 点 ...
- python: numpy--函数 shape用法
http://blog.csdn.net/u010758410/article/details/71554224 shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩 ...
- 准备mybatis-spring
spring-mybatis下载:https://mvnrepository.com/artifact/org.mybatis/mybatis-spring 导入mybatis-spring-2.0. ...
- jQuery筛选--find(expr|obj|ele)和siblings([expr])
find(expr|obj|ele) 概述 搜索所有与指定表达式匹配的元素.这个函数是找出正在处理的元素的后代元素的好方法 参数 expr 用于查找的表达式 jQuery object 一个用于 ...