文章目录
一、反射实战案例二、面向对象魔法方法三、魔法方法笔试题四、元类简介五、产生类的两种方式六、元类基本使用七、元类进阶一、反射实战案例
1.获取配置文件中所有大写的配置 小写的直接忽略 组织成字典配置文件内容NAME = 'LebronJames'INFO = 'DwightHoward'money = 100000AGE = 36logo = 'king'解法import settings # 导入文件new_dict = {} # 创建空字典# print(dir(settings)) # dir方法获取对象中可以使用的方法for i in dir(settings):if i.isupper(): # 如果名字是纯大写 那么获取该大写名字对应的值v = getattr(settings, i) # getattr 获取对应的值new_dict[i] = v # i= k v = vprint(new_dict)result:{'AGE': 36, 'INFO': 'DwightHoward', 'NAME': 'LebronJames'}2.模拟操作系统cmd终端执行用户命令class WinCmd(object):def dir(self):print('dir获取当前目录下所有的文件名称')def ls(self):print('ls获取当前路径下所有的文件名称')def ipconfig(self):print('ipconfig获取当前计算机的网卡信息')obj = WinCmd()while True:cmd = input('请输入您的命令>>>:')if hasattr(obj, cmd):cmd_name = getattr(obj, cmd)cmd_name()else:print('%s 不是内部或外部命令,也不是可运行的程序或批处理文件' % cmd)
二、面向对象魔法方法
什么是魔法方法?魔法方法就是类中定义双下的方法为什么叫做魔法方法呢?因为这些方法都是达到某个条件自动触发的 无需调用__init__方法在给对象设置独有的数据的时候会自动触发专业术语(实例化)
下列讲解的魔法方法都必须明确的知道的触发的条件__init__class MyClass(object):def __init__(self,name):self.name = namem = MyClass('LebronJames')print(m.__dict__)# {'name': 'LebronJames'}'''如果是空的则也是触发{}'''
__str__class MyClass(object):def __str__(self):print('这是__str__方法')return '必须需要返回一个字符串数据' # 如果没返回值报错m = MyClass()print(m)# 这是__str__方法 必须需要返回一个字符串数据''' 对象被执行打印操作的时候会自动触发 返回什么数据就展示什么数据'''
__call__class MyClass(object):def __call__(self, *args, **kwargs):print('__call__方法')print(args) # args 接受多余的数字位置参数print(kwargs) # kwargs 接受多余的字典关键词参数m = MyClass()# 使用call方法 对象加()可以直接调用 ()里面可以添加参数m(1, 2, name='LebronJames', age=36) # __call__方法 (1, 2) {'name': 'LebronJames', 'age': 36}"""对象加括号调用 自动触发该方法"""
__getattr__class MyClass(object):def __getattr__(self, item):print('__getattr__', item)return '您想要获取的属性名:%s不存在' % item# 该方法返回什么 对象获取不存在的属性名就会得到什么m = MyClass()print(m.age)# 形参item就是对象想要获取的不存在的属性名'''当对象获取一个不存在的属性名 自动触发'''__setattr__class MyClass(object):def __setattr__(self, key, value):print("__setattr__")print(key)# key == nameprint(value)# value == LebronJamesm = MyClass()m.name = 'LebronJames'"""对象操作属性值的时候自动触发>>>: 对象.属性名=属性值"""__del__class MyClass(object):def __del__(self):print('__del__')# 触发时 打印__del__m = MyClass()del m# 删除对象触发 __del__'''对象在被删除(主动 被动)的时候自动触发'''__getattribute__class MyClass(object):def __init__(self, name):self.name = namedef __getattribute__(self, item):print('__getattribute__')return super().__getattribute__(item) # 修改了原本的值 给他放回去就好了m = MyClass('LebronJames')# 给新对象m__init__传nameprint(m.name)# 调取m里面那么 结果None 因为你修了getattribute 结果__getattribute__LebronJames'''对象获取属性的时候自动触发 无论这个属性存不存在 当类中既有__getattr__又有__getattribute__的时候 只会走后者'''__enter____exit__# 两个一起配套使用class MyClass(object):def __init__(self, name):self.name = namedef __enter__(self):print('__enter__')return 'LebronJames'def __exit__(self, exc_type, exc_val, exc_tb):print('__exit__')m = MyClass('LebronJames')with m as f:# 对象被with语法执行print(f)# return什么的到什么"""对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么""""""对象被with语法执行并运行完with子代码之后 自动触发"""
三、魔法方法笔试题
补全以下代码 执行之后不报错class Context:passwith Context() as f:f.do_something()解法:class Context:def __enter__(self):return self# 返回一个对象 再去调用do_somethingdef __exit__(self, exc_type, exc_val, exc_tb):passdef do_something(self):passwith Context() as f:f.do_something()
四、元类简介
name = 'LebronJames'print(type(name))# <class 'str'>
基础阶段我们使用type来查找数据的数据类型但是学了面向对象之后 发现查看的不是数据类型 而是数据所属的类我们定义的数据类型 其实本质还是通过各个类产生了对象Class str:passprint(type(str))# <class 'type'>我们也可以理解为type用于查看产生当前对象的类是谁class MyClass:passobj = MyClass()print(type(obj)) # 查看产生对象obj的类:<class '__main__.MyClass'>print(type(MyClass)) # 查看产生对象MyClass的类:<class 'type'>通过上述推导 得出结论 自定义的类都是由type类产生的我们将产生类的类称之为 '元类'
五、产生类的两种方式
1.Class关键字Class MyClass:pass2.利用元类typetype(类名, 类的父类, 类的名称空间)类名必须首字母大写学习元类其实就是掌握了类的产生过程 我们就可以在类的产生过程中高度定制化类的行为
六、元类基本使用
class MyMetaClass(type):pass"""只有继承了type的类才可以称之为是元类"""class MyClass(metaclass=MyMetaClass):pass"""如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass声明"""类中的__init__用于实例化对象元类中__init__用于实例化类class MyMetaClass(type):def __init__(self, what, bases=None, dict=None):# 必须要传的参数 缺一不可 print('别晕')print('what', what) # 类名print('bases', bases) # 类的父类print('dict', dict) # 类的名称空间if not what.istitle(): # 如果首字母不是大写则自动报错raise Exception('首字母必须大写 你会不会写python 面向对象学过吗 lowB')super().__init__(what, bases, dict)# 让它走原来的————init__class myclass(metaclass=MyMetaClass): # 首字母m 变成大写就不会报错pass
七、元类进阶
元类不单单可以控制类的产生过程 其实也可以控制对象的对象加括号执行产生该对象类里面的双下call类加括号执行产生该类的元类里面的双下call
需求:实例化对象 所有的参数都必须采用关键字参数的形式class MyMetaClass(type):def __call__(self, *args, **kwargs):print('__call__')if args:raise Exception('必须用关键字参数传参')super().__call__(*args, **kwargs)class MyClass(metaclass=MyMetaClass):def __init__(self, name, age):self.name = nameself.age = ageprint('__init__')obj = MyClass(name='LebronJames', age=19)'''如果我们想要定制对象的产生过程可以操作元类里面的__call__''''''如果我们想要定制类的产生过程可以操作元类里面的__init__'''
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请
点赞收藏+关注
谢谢支持!
如果觉得《Python面向对象魔法 元类简介及使用》对你有帮助,请点赞、收藏,并留下你的观点哦!