反射与元类

反射与元类

反射实战案例

1.案例1
import settings # 调用我们呢刚刚配置的文件
new_dic = {}  # 制造一个空字典
print(dir(settings))  # 将settings内部的所有可以使用句点符点出来的功能都给他展示出来
# ['AGE', 'HOBBY', 'NAME', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
for i in dir(settings):
    if i.isupper():  # 判断是否为纯大写,如果是纯大写的话那么就获取该大写名字所对应的值
        value = getattr(settings, i)  # 获得对所对应的属性
        new_dic[i] = value # 生成一个字典属性将大写字母的值当作字典的k,然后属性当作v值并纯给之前定义的字典
print(new_dic)  # 打印字典
2.模拟cmd终端命令
class windows():
    def dir(self):
        print('dir获取当前目录下所有文件名称')
    def ls(self):
        print('ls获取当前路径下所有文件名称')
    def ipconfig(self):
        print('ipconfig获取当前计算机的网卡信息')
obj = windows()
while True:
    cmd = input('请输入您的指令')
    if hasattr(obj, cmd):
        cmd_name = getattr(obj,cmd)
        cmd_name()
    else:
        print(f'{cmd} 不是内部命令或外部命令,也不是可运行的程序或批处理文件')

image

常见魔法方法

1.常见魔法
class MyClass(object):
    def __init__(self, name):  # __init__() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值
        print('from__init__')
        pass
        self.name = name
    def __str__(self):  # print([对象]) 是个字符串的时候触发 __str__ 的执行
        print('from__str__')
        return f"对象名称:{self.name}"
    def __call__(self, *args, **kwargs):  # [对象] + ( ) 就触发 __call__ 的执行
        print(args)
        print(kwargs)
        print('from __call__')
    def __getattr__(self, item):  # 在 [对象].[属性] 获取属性不存在的时候会触发它的执行
        print('from __getattr', item)
        return f'您想要获得的属性值:{item}不存在'
    def __setattr__(self, key, value):  # 在 [对象].[属性] = [值] 设置属性值的时候就会触发它的执行
        print(key)
        print(value)
        print('from __setattr')
        super.__setattr__(self, key, value)
    def __del__(self):  # 在 del [对象].[属性] 删除属性的时候会触发它的执行
        print('from __del__')
        pass
    def __getattribute__(self, item):  # 先执行 __getattribute__—>去类的名称空间找—>__getattr__(本质是去对象自己的名称空间找)
        print('from __getattribute__')
        return super(MyClass, self).__getattribute__(item)
    def __enter__(self):  # 上下文管理协议就是 with 语句, 为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__()和__exit__()方法
        print('from __enter__')
    def __exit__(self, exc_type, exc_val, exc_tb):  # 如果__exit__()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
        print('from __exit__')



obj = MyClass('joseph')
obj1 = MyClass('jason')
print(obj.name)  # 获取对象拥有的属性名name
print(obj.age)  # 获取对象不存在的属性名age
print(obj.pwd)  # 获取对象不存在的属性名pwd
print(obj.__dict__)
print(obj.name)
# del obj
print(obj.name)
with obj as f:
    print(f)

with open() as f:
    pass

image

常见魔法方法笔试题

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 f:
    f.do_something()

image

元类简介

元类是什么?

​ 所有的对象都是实例化或者说是通过调用类而得到的,python中一切皆对象,通过class关键字定义的类本质也是对象,对象又是通过调用类得到的,因此通过class关键字定义的类肯定也是调用了一个类得到的,这个类就是元类。

怎样辨别元类

​ 由于在python3中没有经典类和新式类的区别,因此python3中object是所有类的基类,那内置元类type又是什么?type是object类的类型,总结来说就是type是object的类型,同时,object又是type的基类,在python3中类和类型是同一种东西,因此对象.__class__和type(对象)得到的结果是一致的,object的基类为空,但是type的基类为object,但是object的类型又是type。

类型

object.__class__
<class 'type'>
type.__class__
<class 'type'>
object.__bases__()
type.__bases__
<class 'object'>
type(object)
<class 'type'>
type(type)
<class 'typ'>

image

产生类的两种方式

1.class关键字
	class MyClass:
        pass

2.利用元类type
	type(类名,类的父类,类的名称空间)
 
"""
学习元类其实就是掌握了类的产生过程 我们就可以在类的产生过程中高度定制化类的行为
	eg:
		类名必须首字母大写
	上述需求就需要使用元类来控制类的产生过程 在过程中校验
"""

image

元类的基本使用

1.只有继承了 type 的类才可以被称为元类
class MyMetaClass(type):
    pass
2.如果像压迫切换产生类的元类的话只通过继承是不可以的,必须通过关键字的形式才可以进行转型
class MyClass(metaclass = MeMetaClass):
    pass
3.__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.istitel():
            print('首字母必须大写如果不大写直接剔除')
            raise Exception('首字母必须大写如果不大写直接剔除')
        super().__init__(what, bases, dict)

image

元类的进阶操作

1.对象加括号执行产生的对象类内部加括号就可以操控内部对象
2.类加括号执行产生该类的元类里面的双下call
3.实例化对象并操控
class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        print('from __call__')  # from __call__
        if args:
            raise Exception('需要根据形参传实参')
        super().__call__(*args, **kwargs)  # from __call__


class MyCalss(metaclass=MyMetaClass):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print('from __init__')  # from __init__


obj1 = MyCalss('joseph', 21)
obj2 = MyCalss(name='joseph', age=21)

image

双下new方法

"""
类产生对象的步骤
	1.产生一个空对象
	2.自动触发__init__方法实例化对象
	3.返回实例化好的对象
"""
__new__方法专门用于产生空对象				骨架
__init__方法专门用于给对象添加属性		  血肉
如果在类中重写了__new__()方法, 我们可以通过 return 出一个实例, 该实例可以直接是 object 实例出来的对象, 也可以是当前类的父类实例出来的对象,__new__() 用于创建实例,所以该方法是在实例创建之前被调用,它是类级别的方法,是个静态方法

image

posted @ 2022-07-30 15:11  Joseph-bright  阅读(28)  评论(0编辑  收藏  举报