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)
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
涉及的四个函数,这四个函数就是普通的内置函数,与print等等没有区别, 没有双下划线,和类里面的双下的那几个不一样
hasattr getattr setattr delattr
class Stu: pass s1 = Stu() #查询属性 print(hasattr(s1,‘name‘)) #False #输出属性 if hasattr(s1,‘name‘): print(getattr(s1,‘name‘)) #增加属性 setattr(s1,‘name‘,‘123‘) print(hasattr(s1,‘name‘)) #True if hasattr(s1,‘name‘): print(getattr(s1,‘name‘)) #123 #删除属性 delattr(s1,‘name‘) print(hasattr(s1,‘name‘)) #False
使用场景:
反射其实就是对属性的增删改查,但是如果直接使用内置的dict来操作,语法繁琐,不好理解
另外一个最主要的问题是,如果对象不是我们自己写的是另一方提供的,我们就必须判断这个对象是否满足要求,也就是是否具我们需要的属性和方法
框架就是已经实现了最基础的所有项目都一样的部分
框架的设计者,不可能提前知道你的对象到底是怎么设计的,以你提供给框架的对象 ,必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情, 当然通过__dict__也是可以实现的只是比较麻烦不容易看, 其实这些方法也就是对__dict__的操作进行了封装
需求:要实现一个用于处理用户的终端指令的小框架
补充导入模块的模块:
#导入用来导入模块的模块 import importlib # 根据模块的路径,拿到模块 (libs文件夹下plugins模块,里面包含WinCMD和LinuxCMD两个类) pl = importlib.import_module("libs.plugins") # 从模块中取出类WinCMD cls = getattr(pl,"WinCMD") # 实例化产生对象 obj = cls() #调用对象的cd方法 obj.cd()
框架代码:
import plugins #也就是导入插件的文件夹 # 框架已经实现的部分 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!") # 创建一个插件对象 调用框架来使用它 linux = plugins.LinuxCMD() #实例化LinuxCMD的对象 run(linux)
插件代码:
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 列出所有文件....")
上述框架代码中 写死了必须使用某个类,并且我们无法提前知道对方的类的位置(plugins), 以及类名(LinuxCMD)
然后框架自己去加载需要的模块,如此一来,框架就与实现代码彻底解耦了,只剩下配置文件来链接框架和插件
配置文件:
# 作为框架使用者 在配置文件中指定你配合框架的类是哪个 CLASS_PATH = "libs.plugins.LinuxCMD"
最终框架代码:
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!") # 框架 得根据配置文件拿到需要的类 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)
元类: 用于创建类的类
万物皆对象,类当然也是对象
默认情况下所有类的元类都是type(可以使用type直接产生类)
class Person(object): name = "123" pass p = Person() print(type(p)) #<class ‘__main__.Person‘> print(type(Person)) #<class ‘type‘>
使用type直接产生类对象:
一个类的三个基本组成部分 1.类的名字(字符类型)
2.类的父类们 (是一个元组或列表)
3.类的名称空间(字典类型)
cls_obj = type("dog",(),{}) print(cls_obj) #<class ‘__main__.dog‘> #和下面直接创建是一个意思 class Dog: pass
元类这样虽然可以创建类,但是这样来有什么意思呢?本来直接用class就可以了!
高度的自定义一个类,对创建的类对象做一些限制,
例如控制类的名字必须以大驼峰的方式来书写
类也是对象,也有自己的类
想到了初始化方法 我们只要找到类对象的类(元类),覆盖其中 init方法就能实现需求
当然我们不能修改源代码,所以应该继承type来编写自己的元类,同时覆盖init来完成需求
代码:
""" 只要继承了type 那么这个类就变成了一个元类 """ # 定义了一个元类 class MyType(type): def __init__(self,clss_name,bases,dict): super().__init__(clss_name,bases,dict) #三个参数或者一个self print(clss_name,bases,dict) if not clss_name.istitle(): #判断首字母大写 raise Exception("你丫的 类名不会写...") #抛出异常 # 为pig类指定了元类为MyType class Pig(metaclass=MyType): #指定自己的元类 pass class Duck(metaclass=MyType): pass
原文:https://www.cnblogs.com/xp1315458571/p/11272844.html