反射、元类

一、反射

  1、什么是反射:就是反省,自省的意思

  反射指的是一个对象应该具备,可以增、删、改、查属性的能力,通过字符串来操作属性

涉及的四个函数,这四个函数就是普通的内置函数,只是没有下划线而已,实现的功能和原理基本一致

hasattr(object,name)  # 判断对象是否实现某个属性
setattr(object,name,value)  # 为对象增加新的属性
getattr(object,name,default) # 从对象中获取某个属性
delattr(object,)  # 从对象中删除某个属性
# 反射
class Person:def __init__(self,name,age,gender):self.name=nameself.age=ageself.gender=gender
p=Person("James",20,"woman")
# print(p.name)
print(hasattr(p,"name"))  # 判断是否是类的属性
if hasattr(p,"name"):print(getattr(p,"name",None)) #从对象中取出属性,第三个值位默认值# 当属性不存在是返回默认值# 为对象添加新的属性
setattr(p,"id","1234")
print(p,id)# 从对象中删除对象
delattr(p,"id")
print(p,id)

>>
True
James
<__main__.Person object at 0x0000018DC46D5E10> <built-in function id>

 

2、为什么需要反射?

  一个类在定义的时候,可能一些属性的设计并不是很完美,而后期需要作出修改过或删除操作属性时,使用 反射可以不需要修改源代码

3、反射的优势:可插拔设计(重点

  使用的场景:反射其实就是对属性的增删改查,但如果直接使用内置的__dict__来操作,语法繁琐不便操作

另一个点就是调用另一方提供的对象时,必须先判断这个对象是否满足需求,也就是判断是否是我们需要的属性和方法。

  动态添加模块功能

"""
反射被称为框架的基石,为什么
因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
所以你提供给框架的对象 必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情,
当然通过__dict__也是可以实现的, 其实这些方法也就是对__dict__的操作进行了封装
需求:要实现一个用于处理用户的终端指令的小框架
框架就是已经实现了最基础的构架,就是所有项目都一样的部分
"""
import importlib
import settings# 框架已经实现的部分
def run(plugin):while True:cmd = input("请输入指令:")if cmd == "exit":break# 因为无法确定框架使用者是否传入正确的对象所以需要使用反射来检测# 判断对象是否具备处理这个指令的方法if hasattr(plugin,cmd):# 取出对应方法方法func = getattr(plugin,cmd)func() # 执行方法处理指令else:print("该指令不受支持...")print("see you la la!")# 创建一个插件对象 调用框架来使用它
# wincmd = plugins.WinCMD()
# 框架之外的部分就有自定义对象来完成# 框架 得根据配置文件拿到需要的类

path = settings.CLASS_PATH
# 从配置中单独拿出来 模块路径和 类名称
module_path,class_name = path.rsplit(".",1)
#拿到模块
mk = importlib.import_module(module_path)
# 拿到类
cls = getattr(mk,class_name)
# 实例化对象
obj = cls()
#调用框架
run(obj)
框架代码
class WinCMD:def cd(self):print("wincmd 切换目录....")def delete(self):print("wincmd 要不要删库跑路?")def dir(self):print("wincmd 列出所有文件....")class LinuxCMD:def cd(self):print("Linuxcmd 切换目录....")def rm(self):print("Linuxcmd 要不要删库跑路?")def ls(self):print("Linuxcmd 列出所有文件....")
插件(调用)

    如此一来,框架就与代码实现了彻底的耦合,只的剩下配置文件

  其实就是当调用其他外界导入的类的功能和方法的时候,是否使用符合当前需求的操作时,用hasattr做一个判断,再用getattr获取属性的方法

二、元类:metaclass

   元类是创建类的类  所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化)

class创建一个类应该细分为四个过程:   

  1.获取类名

  2.获取基类

  3.获取名称空间

  4.实例化元类得到类

总结:元类即 用于产生类的类

 

2、自定义元类控制类的创建: 

  通过type高度定义一个类,例如要求所有的方法名称必须小写,类名称必须大写开头等

class MyMate(type):#关键字typedef __init__(self,name,bases,dic):print("run")if not dic.get("__doc__"):raise TypeError("类必须有文档注释!")if not name.istitle():raise TypeError("类名必须大写开头!")super().__init__(name,bases,dic)
class Foo(object,metaclass=MyMate):  #绑定元类pass

3、默认情况下所有类的元类都是type

验证:

class Person:pass
p=Person()
print(type(p))
print(type(Person))>>
<class '__main__.Person'>
<class 'type'>   # Person的类型是type

 4、学习元类的目的:高度的自定义一个类,例如控制类的名字必须以大驼峰体的方式来书写、

 

  想到了初始化方法  我们只要找到类对象的类(元类),覆盖其中__ init__方法就能实现需求

当然我们不能修改源代码,所以应该继承type来编写自己的元类,同时覆盖__init__来完成需求

# 定义一个元类
class MyType(type):def __init__(self,clss_name,bases,dict): #继承后用super调用super().__init__(clss_name,bases,dict)print(clss_name,bases,dict)if not clss_name.istitle():raise Exception("类名写错了~")
class pig (metaclass=MyType):print("绑定了元类~")
class Duck(metaclass=MyType):print("规定的协议要遵守~")MyType("pig",(),{})

 5、元类中调用__call__方法

  当你调用类对象时会自动执行元类中的__call__方法,并将这个类本身作为第一个参数传入,以及后面的数,

覆盖元类中的__call__之后,这个类无法产生对象,必须调用super().__call__来完成对象的创建,并返回其返回值。

实现将对象的所有属性名称传为大写:

实现将对象的所有属性名称转化为大写
class MyType(type):def __call__(self, *args, **kwargs):new_arg = []   # 要求的书写规范for a in args:new_arg.append(a.upper()) # 转换为大写print(new_arg)print(kwargs)return super().__call__(*new_arg,**kwargs)
class Person(metaclass=MyType):def __init__(self,name,gender):self.name=nameself.gender=genderp=Person(name="jack",gender="man")
print(p.gender)
print(p.name)>>[]
{'name': 'jack', 'gender': 'woman'}
jack
woman

 注意:一旦覆盖了call必须调用父类的call方法来产生对象并返回这个对象

 6、__new__的方法:

  当你创建类的对象时,会先执行元类中的__new__ 方法

  执行了__new__函数,就不会再执行__init__,因为__new__函数是真正用于创建类的方法,只有创建类成功了才会执行__init__函数,__new__必须要有返回值且返回值类型为__type__时才会执行__init__函数,

 

class Meta(type):def __new__(cls, *args, **kwargs):print(cls) # 元类自己print(args) # 创建类需要的几个参数  类名,基类,名称空间print(kwargs) #空的 print("new run")# return super().__new__(cls,*args,**kwargs)obj = type.__new__(cls,*args,**kwargs)return objdef __init__(self,a,b,c):super().__init__(a,b,c)print("init run")
class A(metaclass=Meta):pass
print(A)

 

 

7、元类实现单例(单例设计模式)

  什么是单例?

 单例是指的是单个实例,指一个类只能有一个实例对象

  为什么要使用单例?

  为了节省资源,当两个对象的数据完全相同时 则没有必要占用两份资源

# 单例n元类
class Single(type):def __call__(self, *args, **kwargs):if hasattr(self,"obj"): #判断是否存在已经有的对象return getattr(self,"obj") # 有就返回
obj = super().__call__(*args,**kwargs) # 没有则创建print("new 了")self.obj = obj # 并存入类中return objclass Student(metaclass=Single):def __init__(self,name):self.name = nameclass Person(metaclass=Single):pass# 只会创建一个对象
Person()
Person()

 

冒泡算法:

总结规律
圈数  是元素个数减一
次数  元素个数 - 1 - (圈数索引) 我们需要两层循环 
一层控制圈数 
一层控制次数 """
ls = [2,1,3,5,100,24,12,12,1,2,1,1,4,32]
for i in range(len(ls)-1):for j in range(len(ls)-1-i):# 如果前面的小于后面的则交换位置if ls[j] > ls[j+1]:ls[j],ls[j+1] = ls[j+1],ls[j]
print(ls)

 

 

 

 

 

 

 

 

 

 

  

转载于:https://www.cnblogs.com/Gaimo/p/11272011.html

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

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

相关文章

html收款页面模板,订单收款.html

&#xfeff;订单收款$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.html; };…

pandas之时间数据

1.时间戳Timestamp() 参数可以为各种形式的时间&#xff0c;Timestamp()会将其转换为时间。 time1 pd.Timestamp(2019/7/13) time2 pd.Timestamp(13/7/2019 13:05) time3 - pd.Timestamp(2019-7-13) time4 pd.Timestamp(2019 7 13 13:05) time5 pd.Timestamp(2019 July 13 …

scikit keras_Scikit学习,TensorFlow,PyTorch,Keras…但是天秤座呢?

scikit kerasWelcome all! In the first episode of this series, I investigated the four most known machine learning frameworks and discussed which of these you should learn depending on your needs and goals.w ^迎阅读所有&#xff01; 在本系列的第一集中 &#…

Educational Codeforces Round 25 C. Multi-judge Solving

题目链接&#xff1a;http://codeforces.com/contest/825/problem/C C. Multi-judge Solving time limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputMakes solves problems on Decoforces and lots of other different onli…

山东省2021年高考成绩查询平台6,山东2021年高考成绩改为6月26日前公布

6月11日&#xff0c;山东省教育厅举行2021年第一次高考新闻发布会&#xff0c;介绍2021年高考基本情况、评卷安排、成绩公布等相关工作。山东省教育招生考试院新闻发言人、普招处处长李春光介绍&#xff0c;根据近期国家有关工作要求和强基计划招生工作需要&#xff0c;原定于6…

如何在vuejs里禁用eslint语法检查工具

eslint好是好&#xff0c;可要求很苛刻&#xff0c;对于我这种写代码很糙的媛。。。。。。 搜索的时候有的说加入 /* eslint-disabled */&#xff08;有用&#xff0c;但只是部分代码享受此待遇&#xff09; 还有说删除.eslintrc.js里包含eslint关键字的块&#xff0c;a---o---…

数据结构两个月学完_这是我作为数据科学家两年来所学到的

数据结构两个月学完It has been 2 years ever since I started my data science journey. Boy, that was one heck of a roller coaster ride!自从我开始数据科学之旅以来已经有两年了 。 男孩 &#xff0c;那可真是坐过山车&#xff01; There were many highs and lows, and…

数学哲学与科学哲学和计算机科学的能动作用,数学哲学与科学哲学和计算机科学的能动作用...

3 数学哲学与计算机科学的能动作用数学哲学对于计算机科学的影响主要表现于以下的事实&#xff1a;一些源于数学哲学(数学基础研究)的概念和理论在计算机科学的历史发展中发挥了十分重要的作用。例如&#xff0c;在此可以首先提及(一阶)谓词演算理论&#xff1a;这是由弗雷格(…

AngularDart4.0 指南- 表单

2019独角兽企业重金招聘Python工程师标准>>> 表单是商业应用程序的主流。您可以使用表单登录&#xff0c;提交帮助请求&#xff0c;下订单&#xff0c;预订航班&#xff0c;安排会议&#xff0c;并执行无数其他数据录入任务。 在开发表单时&#xff0c;创建一个数据…

迈向数据科学的第一步:在Python中支持向量回归

什么是支持向量回归&#xff1f; (What is Support Vector Regression?) Support vector regression is a special kind of regression that gives you some sort of buffer or flexibility with the error. How does it do that ? I’m going to explain it to you in simpl…

jQuery事件整合

一、jQuery事件 1、focus&#xff08;&#xff09;元素获得焦点 2、blur&#xff08;&#xff09;元素失去焦点 3、change&#xff08;&#xff09; 表单元素的值发生变化&#xff08;可用于验证用户名是否存在&#xff09; 4、click&#xff08;&#xff09; 鼠标单击 5、dbc…

tableau跨库创建并集_刮擦柏林青年旅舍,并以此建立一个Tableau全景。

tableau跨库创建并集One of the coolest things about making our personal project is the fact that we can explore topics of our own interest. On my case, I’ve had the chance to backpack around the world for more than a year between 2016–2017, and it was one…

1.0 Hadoop的介绍、搭建、环境

HADOOP背景介绍 1.1 Hadoop产生背景 HADOOP最早起源于Nutch。Nutch的设计目标是构建一个大型的全网搜索引擎&#xff0c;包括网页抓取、索引、查询等功能&#xff0c;但随着抓取网页数量的增加&#xff0c;遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索引问题。20…

如何实现多维智能监控?--AI运维的实践探索【一】

作者丨吴树生&#xff1a;腾讯高级工程师&#xff0c;负责SNG大数据监控平台建设。近十年监控系统开发经验&#xff0c;具有构建基于大数据平台的海量高可用分布式监控系统研发经验。 导语&#xff1a;监控数据多维化后&#xff0c;带来新的应用场景。SNG的哈勃多维监控平台在完…

使用Python和MetaTrader在5分钟内开始构建您的交易策略

In one of my last posts, I showed how to create graphics using the Plotly library. To do this, we import data from MetaTrader in a ‘raw’ way without automation. Today, we will learn how to automate this process and plot a heatmap graph of the correlation…

请对比html与css的异同,css2与css3的区别是什么?

css主要有三个版本&#xff0c;分别是css1、css2、css3。css2使用的比较多&#xff0c;因为css1的属性比较少&#xff0c;而css3有一些老式浏览器并不支持&#xff0c;所以大家在开发的时候主要还是使用css2。CSS1提供有关字体、颜色、位置和文本属性的基本信息&#xff0c;该版…

ipywidgets_未来价值和Ipywidgets

ipywidgetsHow to use Ipywidgets to visualize future value with different interest rates.如何使用Ipywidgets可视化不同利率下的未来价值。 There are some calculations that even being easy becoming better with a visualization of his terms. Moreover, the sooner…

计算机主机后面辐射大,电脑的背面辐射大吗

众所周知&#xff0c;电子产品的辐射都比较大&#xff0c;而电脑是非常常见的电子产品&#xff0c;它也存在着一定的辐射&#xff0c;那么电脑的背面辐射大吗?下面就一起随佰佰安全网小编来了解一下吧。有资料显示&#xff0c;电脑后面的辐射比前面大&#xff0c;长期近距离在…

装饰器3--装饰器作用原理

多思考&#xff0c;多记忆&#xff01;&#xff01;&#xff01; 转载于:https://www.cnblogs.com/momo8238/p/7217345.html

用folium模块画地理图_使用Folium表示您的地理空间数据

用folium模块画地理图As a part of the Data Science community, Geospatial data is one of the most crucial kinds of data to work with. The applications are as simple as ‘Where’s my food delivery order right now?’ and as complex as ‘What is the most optim…