反射、元类

一、反射

  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,一经查实,立即删除!

相关文章

Java—简单的图书管理系统

简单的图书管理系统 通过数据源和DAO对象访问数据库。其中JavaBeans实现模型&#xff0c;访问数据库&#xff0c;Servlet实现控制器&#xff0c;JSP页面实现视图。 • 模型包括2个JavaBean&#xff1a;BookBean用于存放图书信息&#xff0c;BookDAO用于访问数据库。 • 控制器包…

成功的秘诀是什么_学习编码的10个成功秘诀

成功的秘诀是什么This post was originally published on Coder-Coder.com.该帖子最初发布在Coder-Coder.com上 。 If you’re teaching yourself how to code, you may have more questions than answers when you’re starting out.如果您正在教自己如何编码&#xff0c;那么…

ZJUT 地下迷宫 (高斯求期望)

http://cpp.zjut.edu.cn/ShowProblem.aspx?ShowID1423 设dp[i]表示在i点时到达终点要走的期望步数&#xff0c;那么dp[i] ∑1/m*dp[j] 1&#xff0c;j是与i相连的点&#xff0c;m是与i相邻的点数。建立方程组求解。重要的一点是先推断DK到达不了的点。须要bfs预处理一下进行…

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; 在本系列的第一集中 &#…

程序员如何学习更好的知识_如何保持学习并成为更好的程序员

程序员如何学习更好的知识by Kevin Gardner凯文加德纳(Kevin Gardner) 如何保持学习并成为更好的程序员 (How to keep learning and become a better coder) Coding has come a long way since the days of Robert Taylor and ARPANET and Sir Tim Berners-Lee and CERN — an…

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…

Java—stream以及集合框架使用

1) 编写Student类&#xff0c;主要属性包括学号、姓名、性别、班级 2) 编写Score类&#xff0c;主要属性包括&#xff1a;学号、课程名、分数 3) 模拟期末考试的成绩统计应用场景&#xff0c;要求 (1) 所有学生名单及对应科目成绩已经初始化在数组中 (2) 要求输出每门课程的所有…

山东省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…

leetcode 888. 公平的糖果棒交换(set)

爱丽丝和鲍勃有不同大小的糖果棒&#xff1a;A[i] 是爱丽丝拥有的第 i 根糖果棒的大小&#xff0c;B[j] 是鲍勃拥有的第 j 根糖果棒的大小。 因为他们是朋友&#xff0c;所以他们想交换一根糖果棒&#xff0c;这样交换后&#xff0c;他们都有相同的糖果总量。&#xff08;一个…

如何使用JavaScript检查输入是否为空

by Zell Liew由Zell Liew 如何使用JavaScript检查输入是否为空 (How to check if an input is empty with JavaScript) Last week, I shared how to check if an input is empty with CSS. Today, let’s talk about the same thing, but with JavaScript.上周&#xff0c;我分…

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

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

AngularDart4.0 指南- 表单

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

(转载)分享常用的GoLang包工具

分享常用的GoLang包工具 包名 链接地址 备注 Machinery异步队列 https://github.com/RichardKnop/machinery Mqtt通信 github.com/eclipse/paho.mqtt.golang go文档http://www.eclipse.org/paho/clients/golang/ 微信开发 https://github.com/chanxuehong/wechat fasthttp包 gi…

迈向数据科学的第一步:在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…

js 触发LinkButton点击事件,执行后台方法

页面 <asp:LinkButton ID"lbtButton" runat"server" CssClass"lbtButton" Font-Underline"false" OnClick"lbtButton_Click"> js function clickButton(filePath, fileName){ __doPostBack(lbtButton, ); } 当执行该…

vue 响应式ui_如何在Vue.js中设置响应式UI搜索

vue 响应式uiAre you thinking of building something awesome with one of the popular modern frameworks out there right now, but don’t know how to get started?您是否正在考虑使用当前流行的现代框架之一来构建出色的东西&#xff0c;但不知道如何入门&#xff1f; …