面向对象之反射,元类
一.反射
1.什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能能力(自省)。
2.python中的反射
反射是所有面向对象编程语言都具备的功能
python中通过一下四个函数来实现反射
1 hasattr(object,name) #判断对象是否拥有某个属性 2 setattr(object,name,value) #为对象增加新的属性 3 getattr(object,name,default) #从对象中获取某个属性 4 delattr(object,name) #从对象中删除某个属性
3.为什么需要反射
一个类在定义的时候,可能一些属性的设计并不是很完美,而后期需要做出修改,或是增加新属性时,使用反射的方式可以不需要修改源代码
反射的另一个优势(重点):可插拔设计
不仅限于修改已有的属性,通过反省能够发现已存在的属性,只要你给我一个对象我就能检查其拥有的属性,从而使用这些属性,而不需要提前了解这些对象,这大大提高了程序的扩展性
案例1:
1 import plugins 2 def run(plugin): 3 while True: 4 cmd = input('请输入指令:').strip() 5 if cmd == 'exit': 6 break 7 if hasattr(plugin,cmd): 8 fun = getattr(plugin,cmd) 9 fun() 10 else: 11 print('该指令不受支持') 12 print(‘已退出’)
1 #plugins 2 3 class Wincmd: 4 def dir(self): 5 print('wincmd列出所有文件。。。') 6 def cd(self): 7 print('wincmd 切换目录。。。') 8 def delete(self): 9 print('wincmd 要不要删除目录。。。 ')
对案例1进行改进,使用动态导入模块
案例2:
1.首先配置settings
class_path = 'lib.plugins.Wincmd'
2.主体框架:
1 import importlib 2 from 面向对象 import settings 3 def run(plugin): 4 while True: 5 cmd = input('请输入指令:') 6 if cmd == 'exit': 7 break 8 if hasattr(plugin,cmd): 9 func = getattr(plugin,cmd) 10 func() 11 else: 12 print('该指令不受支持') 13 print('see you la la') 14 15 path,class_name = settings.class_path.rsplit('.',1) 16 mk = importlib.import_module(path) #找到模块(文件) 17 cls = getattr(mk,class_name) #通过反射,模块与类名,得到类 18 obj = cls() #实例化对象 19 run(obj) #调用函数 传入对象
二.元类
1.什么是元类?
在Python中,一切皆对象,类也是对象。
验证一下:
1 class Person: 2 pass 3 print(type(Person)) 4 #<class 'type'>
由此看来Person类属于type类,是由type类产生的对象。
因此可以推导出:
用于实例化产生类的类称之为元类,就是此时的type类
2.创建类的流程分析:
一个类有三个基本组成部分:
1.类的名字(字符类型)
2.类的父类们(是一个元组或列表)
3.类的名称空间(字典类型)
用另一种方式出创建类
cls_obj = type('dog',(),{}) #同样可以创建类
3.自定义元类,通过自定义原来创建类
创建类是由type完成的type中必然包含了创建了的具体代码,现在需要对这些代码进行修改,两种方式:
1.修改type源代码不可取
2.创建新的元类,使用自己的元类来创建类从而实现定制类
一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过该继承type
来自定义元类,然后使用metaclass关键字参数为一个类指定元类
1 class MyType(type): 2 def __init__(self,clss_name,bases,dict): 3 super().__init__(clss_name,bases,dict) 4 5 class Person(metaclass = MyType): 6 pass
4.在自定义元类中通过覆盖type类中的__init__来控制定义类
下面有个需求,我们高度自定义一个类,需要控制类的名字必须以大驼峰的方式来书写
这是需要在自定义元类中覆盖type类中的__init__方法。
class MyType(type):def __init__(self,cls_name,bases,dict):super().__init__(cls_name,bases,dict)if not cls_name.istitle():raise Exception('类名要大写的驼峰')class Pig(metaclass = MyType):pass
5.元类中call方法(当你想要控制对象的创建过程时)
当你调用类对象时会自动珍惜元类中的__call__方法,并将这个类本身作为第一个参数传入,以及右面的一堆参数,覆盖元类中的call之后,这个类就无法产生对象,必须调用super().__call__来完成对象的创建,并返回其返回值。
案例:实现将对象的所有属性名成转为大写
class MyType(type):def __call__(self,*args,**kwargs):for k,v in kwargs.items():kwargs[k] = v.upper()return super().__call__(*args,**kwargs)class Person(metaclass = MyType):def __init__(self,name,gender):self.name = nameself.gender = gender p = Person(name = 'jack',gender = 'man') print(p.name) print(p.gender)
注意:一旦覆盖了call必须调用父类的call方法来产生对象并返回这个对象
6.单例设计模式
单例:指的是一个类产生一个对象
为什么要使用单例:单例是为了节省资源,当一个类的所有对象属性全部相同时,则没有必要创建多个对象
需求:只生成一个对象
1 class Single(type): 2 def __call__(self, *args, **kwargs): 3 if hasattr(self,"obj"): #判断是否存在已经有的对象 4 return getattr(self,"obj") # 有就返回 5 obj = super().__call__(*args,**kwargs) # 没有则创建 6 self.obj = obj # 并存入类中 7 return obj 8 9 class Person(metaclass=Single): 10 pass 11 12 # 只会创建一个对象 13 Person() 14 Person() 15 #创建再多个对象都是同一个
转载于:https://www.cnblogs.com/s686zhou/p/11271154.html
面向对象之反射,元类相关推荐
- python 元类的call_python3 全栈开发 - 内置函数补充, 反射, 元类,__str__,__del__,exec,type,__call__方法...
python3 全栈开发 - 内置函数补充, 反射, 元类,__str__,__del__,exec,type,__call__方法 一, 内置函数补充 1,isinstance(obj,cls)检查 ...
- Python面向对象魔法、元类简介及使用
文章目录 一.反射实战案例 二.面向对象魔法方法 三.魔法方法笔试题 四.元类简介 五.产生类的两种方式 六.元类基本使用 七.元类进阶 一.反射实战案例 1.获取配置文件中所有大写的配置 小写的直接 ...
- day24 反射\元类
反射 reflect # 什么是反射, 其实是反省,自省的意思,反射指的是一个对象应该具备,可以检测,修改,增加自身属性的能力. # 反射就是通过字符串操作属性,涉及的四个函数,这四个函数就是普通的内 ...
- python_面向对象进阶之元类
1:在一个py文件中,创建一个类 在另外一个py文件中,引用这个类 创建一个Person类的实例是在第6行 类是在第4行创建的** from引入模块之后,则动态的创建一个Person类(因为引入时,会 ...
- python 元类 type_python Class:面向对象高级编程 元类:type
type的用法: 1.普通的type用法:检查类型class my(object): def hello(self, name='world'): print('Hello, %s.' % name) ...
- java 元类_[译]什么是元类metaclass?
类即对象 在理解元类之前,需要先掌握Python中的类,Python中类的概念与SmallTalk中类的概念相似. 在大多数语言中,类是用来描述如何创建对象的代码段,这在Python中也是成立的: & ...
- Python 第二十六章 面向对象 元类+反射+双下方法
元类 class A:pass obj = A() print(type('abc')) print(type([1,2,3])) print(type((22,33)))# type 获取对象从属于 ...
- python元类、反射及双线方法
元类 print(type('abc')) print(type(True)) print(type(100)) print(type([1, 2, 3])) print(type({'name': ...
- delstr函数python_python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法详解...
一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 classFoo(object):passobj=Foo()print(isinstance(obj ...
最新文章
- 2019最新进展 | Transformer在深度推荐系统中的应用
- [python]逆水行舟不进则退(1)
- 年轻人,莫把技术当全部
- 基于SignalR的站点有连接数限制问题及解决方案
- IT兄弟连 JavaWeb教程 文件下载技术
- 揭秘315黑客wifi,如何保障APP数据安全
- centos安装守护进程工具supervisor
- 利用JavaScript生成随机数字!
- vue调用日期_Vue 前端开发——打印功能实现
- 苹果cms10整合dplayer播放器
- lbp7660cdn设置网络打印,佳能LBP7660Cdn打印机驱动官方版
- linux无法更改屏幕亮度调节软件,在Deepin系统中安装闭源显卡驱动后屏幕亮度无法调节的解决...
- iphone计算机输入文字,10个鲜为人知的iPhone实用技巧 全知道的算我输!
- Lenovo 使用BoMC工具制作微码升级U盘刷新System x
- Omap4470 USB驱动分析之注册过程
- HDU 2708 Vertical Histogram 【模拟 输出格式】
- 大系统观:1.4时间之矢
- 【Nav2中文网】五、普通教程(三)用实体Turtlebot3机器人导航
- 浅谈SAP FICO—总账科目
- 数据结构c语言版二叉树的顺序存储表示,数据结构(十一) -- C语言版 -- 树 - 二叉树基本概念...
热门文章
- HTML一条线匀速一定区域运动,通用的匀速运动框架如何打造
- 北航os实验lab2笔记
- linux下postgresql创表添加数据
- 本科数学基础差的感觉 SLAM 很难,如何去提高?
- 表格数据横向转纵向并在el-table中渲染
- total-vm anon-rss file-rss shmem-rss含义
- python容易挂科吗_如何应付大学的python考试而不至于挂科?
- 聚乙烯醇(PVA)/壳聚糖(CTS)/氧化石墨烯(GO)水凝胶吸附和解吸实验(供应PNIPA/膨润土复合/聚乙烯醇/魔芋胶复合/HAP纳米纤维/GelMA复合丝素蛋白(SF)复合水凝胶等)
- html5怎么修改图片大小,HTML5 javascript修改canvas的大小
- 深度解析上海互联网产业为何沉沦