双下方法和元类
2022/4/11 23:12:53
本文主要是介绍双下方法和元类,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
总结
一、反射实际案例
二、面向对象的双下方法
三、元类
四、元类进阶
五、双下new方法
一、反射实际案例
# 反射提供了使用者不需要考虑代码,操作系统的数据和功能的方法 # 利用面向对象编写系统终端功能 class WinCmd(object): def ls(self): print('windows系统正在执行ls命令') def dir(self): print('windows系统正在执行dir命令') def cd(self): print('windows系统正在执行cd命令') obj = WinCmd() def run(obj): while True: cmd = input('请输入您的指令>>>:').strip() if hasattr(obj, cmd): func_name = getattr(obj,cmd) func_name() else: print('cmd command not found') # 指令没有找到 run(obj) # 通过输入指令,来进行运行 # 同理我们也可以模拟linux系统 class LinuxCmd(object): def ls(self): print(' Linux系统正在执行ls命令') def dir(self): print(' Linux系统正在执行dir命令') def cd(self): print(' Linux系统正在执行cd命令') obj = LinuxCmd() def run(obj): while True: cmd = input('请输入您的指令>>>:').strip() if hasattr(obj, cmd): func_name = getattr(obj,cmd) func_name() else: print('cmd command not found') # 指令没有找到 run(obj) # 只需要增加对象就可以
二、面向对象的双下方法
""" 面向对象中的双下方法很神奇,而且有些双下方法不需要可以的调用,到达某个条件就会自动触发 eg: __init__ 在对象实例化的时候 就会自动触发 """
- 双下str方法(str)
__srt__ 对象被执行打印(print、前端展示)操作的时候自动触发 这个方法必须返回字符串类型的数据,如果不是直接报错 '用来更加精准的描述对象' class student(object): def __init__(self, name): self.name = name def __str__(self): print('哎嘿哎嘿') return '芜湖' obj = student('owen') print(obj) # 图为: def __str__(self): print('哎嘿哎嘿') return 123 # 当返回不是字符串时,报错
- 双下del(del)
__del__ 对象被执行(被动、主动)删除操作之后自动执行 # 被动操作 class student(object): def __init__(self, name): self.name = name def __str__(self): print('哎嘿哎嘿') return '芜湖' def __del__(self): print('del执行') obj = student('owen') print('起飞')
# 主动操作 class student(object): def __init__(self, name): self.name = name def __str__(self): print('哎嘿哎嘿') return '芜湖' def __del__(self): print('del执行') obj = student('owen') del obj print('起飞')
- 双下gettattr(getattr)
对象查找不存在名字的时候自动触发 class Student(object): def __init__(self, name): self.name = name def __getattr__(self, item): print('执行getattr',item) obj = Student('owen') print(obj.name) print(obj.age)
- 双下setattr(setattr)
class Student(object): def __init__(self, name): self.name = name def __setattr__(self, key, value): print('触发setattr') print(key, value) obj = Student('owen') obj.age = 10
- 双下call(call)
# 可以支持对象加括号,可以传值,还可以返回值 class Student(object): def __init__(self, name): self.name = name def __call__(self, *args, **kwargs): print('执行call', args, kwargs) return '起飞' # obj() obj = Student('owen') print(obj(111))
- 双下enter(enter) 和 双下exit(exit)
# 之所以放他们在一块是因为他们固定在一起,要不然直接报错 class Student(object): def __init__(self, name): self.name = name def __enter__(self): # 对象被执行with上下文管理语法开始自动触发 # 该方法返回什么as后面的变量名就会得到什么 print('执行enter') def __exit__(self, exc_type, exc_val, exc_tb): # 对象被执行with上下文管理语法结束之后自动触发 print('执行exit') obj = Student('owen') with obj as f: print(111) print(222)
- 双下getattribute(getattribute)
# 只要对象查找名字无论名字是否存在都会执行该方法 # 如果类中有__getattribute__方法 那么就不会去执行__getattr__方法 class Student(object): def __init__(self, name): self.name = name def __getattribute__(self, item): print('执行getattribute') obj = Student('owen') print(obj.name)
笔试题讲解
1.让字典具备句点符查找值的功能 # 我们要区分名称空间的名字还是数据k:v键值对 class MyDict(dict): def __getattr__(self, item): return self.get(item) def __setattr__(self, key, value): self[key] = value obj = MyDict({'name':'owen', 'age': 20}) print(obj.name) print(obj.age) obj.gender = 'male' print(obj)
2.补全下列代码 使其运行不报错 原题: """ class Context: pass with Context() as ctx: ctx.do_something() """ # 书写 1. 看到with方法就知道定义双下enter和双下exit 2.变量名加点绑定方法增加一个do_something方法 class Context: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass def do_something(self): pass with Context() as ctx: ctx.do_something()
三、元类
1、含义
# 元类——产生类的类 print(type(111)) # <class 'int'> print(type([11, 22, 33])) # print(type([11, 22, 33])) 我们这里使用type查看就是当前对象所属的类名称 class MyClass(object): pass obj = MyClass() print(type(obj)) # <class '__main__.MyClass'> print(type(MyClass)) # <class 'type'> class Student: pass print(type(Student)) # <class 'type'> # 所以我们在这里得到 """ type 就是所有类的默认的元类 """
2、产生类的两种表现形式
1.class关键字 class MyClass(object): pass print(MyClass) # <class '__main__.MyClass'> 2.type元类 type(类名,父类,类的名称空间) res = type(MyClass,(),{}) print(res) # <class '__main__.MyClass'> """ 我们学习元类主要因为 元类能够控制类的创建,相当于我们可以高度定制类的行为。 eg:我们掌握了物品的生产过程,就可以在生产过程中做任何的额外操作 实际应用:要求类的名字必须首字母大写 因为我们现在对类的产生过程还没有那么了解,所以我们思考对象的产生过程为>>>>>类里面的__init__方法,所以我们判断类的产生过程为>>>>>元类里面的__init__方法 """
3、元类的基本使用
""" 元类是不能通过继承的方式来直接指定 ,需要通过关键字参数(metaclass)的形式来修改""" class MyTypeClass(type): def __init__(self,cls_name, cls_bases, cls_dict): # 双下init黄色就是表达这个init方法被修改 print(self,cls_name, cls_bases, cls_dict) # <class '__main__.M1'> M1 () {'__module__': '__main__', '__qualname__': 'M1', 'school': '安徽大学'} if not cls_name.istitle(): # 判断首字母是不是小写 raise Exception('类名首字母要大写呀') super().__init__(cls_name, cls_bases, cls_dict) class M1(metaclass=MyTypeClass): school = '安徽大学'
四、元类进阶操作
# 思考__call__操作方法 对象加括号会制动执行产生这个对象的类里面的__call__,并且这个方法返回什么对象加括号就会得到什么 so:类加括号会执行元类的里面的__call__该方法返回什么,类加括号就会得到什么 class MyTypeClass(type): def __call__(self,*args, **kwargs): return 'bibibibi' class MyClass(metaclass=MyTypeClass): pass obj = MyClass() print(obj) """类里面的__init__方法和元类里面的__call__方法执行的先后顺序""" class MyTypeClass(type): def __call__(self,*args, **kwargs): print('__call__ run') # super().__init__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): print('__init__ run') self.name = name obj = MyClass() # __call__ run 这里就是先走双下call,所以一个对象的产生先经历元类里面的双下call """强制规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数""" class MyTypeClass(type): def __call__(self,*args, **kwargs): if args: raise Exception('必须全部用关键字参数') super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): self.name = name # obj = MyClass('owen') # 报错 obj = MyClass(name= 'owen') """ 如果想高度定制类的产生过程 那么编写元类里面的__init__方法 如果想高度定制对象的产生过程 那么编写元类里面的__call__方法 """
五、双下new方法
""" __new__用来产生空对象(类) 相当于人的骨架 __init__用来实例化对象(类) 相当于人的血肉 """ class MyTypeClass(type): def __new__(cls, *args, **kwargs): obj = type.__new__(cls, *args, **kwargs) return obj class MyClass(metaclass=MyTypeClass): def __init__(self,name): self.name = name obj = MyClass('owen') print(obj) # <__main__.MyClass object at 0x0000021373C891D0> 完整版本: """ 注意:并不是所有的地方都可以直接调用__new__ 该方法过于底层 如果是在元类的__new__里面 可以直接调用 class Meta(type): def __new__(cls, *args, **kwargs): obj = type.__new__(cls,*args,**kwargs) return obj 如果是在元类的__call__里面 需要间接调用 class Mate(type): def __call__(self, *args, **kwargs): obj = object.__new__(self) # 创建一个空对象 self.__init__(obj,*args,**kwargs) # 让对象去初始化 return obj """
这篇关于双下方法和元类的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-10百万架构师第十三课:源码分析:Spring 源码分析:Spring核心IOC容器及依赖注入原理|JavaGuide
- 2025-01-10便捷好用的电商API工具合集
- 2025-01-09必试!帮 J 人团队解决物流错发漏发的软件神器!
- 2025-01-09不容小觑!助力 J 人物流客服安抚情绪的软件!
- 2025-01-09为什么医疗团队协作离不开智能文档工具?
- 2025-01-09惊叹:J 人团队用啥软件让物流服务快又准?
- 2025-01-09如何利用数据分析工具优化项目资源分配?4种工具推荐
- 2025-01-09多学科协作难?这款文档工具可以帮你省心省力
- 2025-01-09团队中的技术项目经理TPM:工作内容与资源优化策略
- 2025-01-09JIT生产管理法:优化流程,提升竞争力的秘诀