Python(面向对象5——高级)
面向对象进阶
一 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)
二 反射(hasattr getattr setattr)
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
- hasattr(object,name)
- 判断object中有没有一个name字符串对应的方法或属性
- getattr(object, name, default=None)
- setattr(x, y, v)
- delattr(x, y)
- #应用举例
- class BlackMedium:
- feature='Ugly'
- def __init__(self,name,addr):
- self.name=name
- self.addr=addr
- def sell_house(self):
- print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
- def rent_house(self):
- print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
- b1=BlackMedium('万成置地','回龙观天露园')
- #检测是否含有某属性
- print(hasattr(b1,'name'))
- print(hasattr(b1,'sell_house'))
- #获取属性
- n=getattr(b1,'name')
- print(n)
- func=getattr(b1,'rent_house')
- func()
- # getattr(b1,'aaaaaaaa') #报错
- print(getattr(b1,'aaaaaaaa','不存在啊'))
- #设置属性
- setattr(b1,'sb',True)
- setattr(b1,'show_name',lambda self:self.name+'sb')
- print(b1.__dict__)
- print(b1.show_name(b1))
- #删除属性
- delattr(b1,'addr')
- delattr(b1,'show_name')
- delattr(b1,'show_name111')#不存在,则报错
- print(b1.__dict__)
- #四个方法的使用演示
- #类也是对象
- class Foo(object):
- staticField = "old boy"
- def __init__(self):
- self.name = 'wupeiqi'
- def func(self):
- return 'func'
- @staticmethod
- def bar():
- return 'bar'
- print getattr(Foo, 'staticField')
- print getattr(Foo, 'func')
- print getattr(Foo, 'bar')
- #反射当前模块成员
- import sys
- def s1():
- print 's1'
- def s2():
- print 's2'
- this_module = sys.modules[__name__]
- hasattr(this_module, 's1')
- getattr(this_module, 's2')
3 为什么用反射之反射的好处
好处一:实现可插拔机制
可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能。
好处二:动态导入模块(基于反射当前模块成员)
三 __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
三者的用法演示
(无限递归是赋值/删除的操作本身,又触发了赋值/删除操作,不断循环)
四 二次加工标准类型(包装)
包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)
- #二次加工标准类
- 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)
- #clear加权限限制
- class List(list):
- def __init__(self,item,tag=False):
- super().__init__(item)
- self.tag=tag
- def append(self, p_object):
- if not isinstance(p_object,str):
- raise TypeError
- super().append(p_object)
- def clear(self):
- if not self.tag:
- raise PermissionError
- super().clear()
- l=List([1,2,3],False)
- print(l)
- print(l.tag)
- l.append('saf')
- print(l)
- # l.clear() #异常
- l.tag=True
- l.clear()
五 __getattribute__
- class Foo:
- def __init__(self,x):
- self.x=x
- def __getattribute__(self, item):
- print('不管是否存在,我都会执行')
- f1=Foo(10)
- f1.x
- f1.xxxxxx
- #_*_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
六 __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'))
- #-----------------------------------------------------------------------
- #自定义format练习
- date_dic={
- 'ymd':'{0.year}:{0.month}:{0.day}',
- 'dmy':'{0.day}/{0.month}/{0.year}',
- 'mdy':'{0.month}-{0.day}-{0.year}',
- }
- class Date:
- def __init__(self,year,month,day):
- self.year=year
- self.month=month
- self.day=day
- def __format__(self, format_spec):
- if not format_spec or format_spec not in date_dic:
- format_spec='ymd'
- fmt=date_dic[format_spec]
- return fmt.format(self)
- d1=Date(2016,12,29)
- print(format(d1))
- print('{:mdy}'.format(d1))
- #------------------------------------------------------------------
- #issubclass和isinstance
- #_*_coding:utf-8_*_
- __author__ = 'Linhaifeng'
- class A:
- pass
- class B(A):
- pass
- print(issubclass(B,A)) #B是A的子类,返回True
- a1=A()
- print(isinstance(a1,A)) #a1是A的实例
七 __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__)
Python(面向对象5——高级)的更多相关文章
- Python面向对象编程高级特性
***这里还是根据网上资料,主要是廖雪峰老师的教程学习的笔记,主要介绍python面向对象的高级特性,笔记不全,只是记录自己觉得容易出错的地方*** 1.python作为一种动态语言,他的动态绑定机制 ...
- Python面向对象的高级编程
数据封装.继承和多态只是面向对象程序设计中最基础的3个概念.在Python中,面向对象还有很多高级特性,允许我们写出非常强大的功能. 我们会讨论多重继承.定制类.元类等概念. 使用__slots__ ...
- Python 面向对象之高级编程
7.面向对象高级编程 7.1使用__slots__ python动态语言,new 对象后绑定属性和方法 Tip:给一个实例绑定的方法,对其他对象无效.可以通过对class绑定后,所有对象可以调用该方法 ...
- python 面向对象高级应用(三)
目录: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__getattr__ 二次加工标准类型(包装) __ ...
- Python学习笔记【第十一篇】:Python面向对象高级
isinstance(obj,cls)和issubclass(sub,super) class Person(object): def __init__(self, name, age, sex, n ...
- python之面向对象的高级进阶
一 .isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object ...
- python面向对象高级:Mixin多重继承
继上一篇学习笔记:python面向对象的继承与多态,本篇就Mixin扩展类的方法写下学习笔记 Mixin Mixin编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是 ...
- Python之路【第十二篇】:Python面向对象高级
一.反射 1 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究 ...
- python 面向对象进阶之内置方法
一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...
随机推荐
- 【NOIP模拟题】小象涂色(概率+期望+递推)
表示数学是个渣... 其实只需要推出每个箱子k次以后的颜色为i的概率就能算出期望了.. 对于区间[l, r]的箱子因为是任意颜色且任意取,所以概率分别为1/c和1/2,那么整体概率就为这两个的乘积.根 ...
- 要立刷金组flag了T_T
刷了那么多银组,发现自己好多不会啊... 果然太弱 在这感谢hzwer神犇的blog.. 大部分题解都从黄学长这里来orz. orz.... 果然我太水
- NData转化
NSdata 与 NSString,Byte数组,UIImage 的相互转换---ios开发 Objective-C 1. NSData 与 NSStringNSData-> NSStringN ...
- 从远程(包括ftp,http等协议)地址获取文件流信息
URL url = new URL("ftp://172.18.251.155:8010/recordsImg/2019-01-28/000008_1548649813267.jpg&quo ...
- 【BZOJ1217】[HNOI2003]消防局的设立 树形DP
[BZOJ1217][HNOI2003]消防局的设立 Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地, ...
- 『SharePoint 2010』Sharepoint 2010 Form 身份认证的实现(基于AD)
一.进管理中心,创建一个应用程序,配置如下: 二.填端口号,和选择form身份认证,以及填写成员和角色,其他都默认就可以了 三.使用SharePoint 2010 Management Shell在里 ...
- Oracle Schema Objects——Tables——Oracle Data Types
Oracle Schema Objects Oracle Data Types 数据类型 Data Type Description NUMBER(P,S) Number value having a ...
- python celery rabbitmq--- pypi image from ustc
https://lug.ustc.edu.cn/wiki/mirrors/help/pypi 那么为啥要用celery ?(http://xiaorui.cc/2014/11/16/celery-ra ...
- 01. Java序列化与反序列化简介
Java对象的序列化与反序列化 ; 给大家讲解一下什么是序列化 & 反序列化 当两个进程进行远程通讯的时候,彼此相互可以发送各种类型的数据,如文本,图片,语音和视频等无论是任何类型,最终都会 ...
- mysql 创建函数ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_f
mysql 创建函数的时候 报错 ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL D ...