python基础25 面对对象和类4

131 阅读4分钟

反射实战案例

# 例1:
 配置文件加载: 创建
import settings       # 获取配置文件中所有大写的配置,小写的直接忽略组织成字典
new_dict = {}
print(dir(settings))  # dir获取括号中对象可以调用的名字    # ['AGE', 'INFO','desc', 'name', '__builti__等一堆双下方法]
for i in dir(settings):
    if i.isupper():   # 如果名字是纯大写,那么获取该大写名字对应的值   'AGE'   'INFO'
        v = getattr(settings, i)
        new_dict[i] = v
print(new_dict)
# 例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方法再给对象设置独有的数据时就会自动触发(实例化)
  • 需要掌握的魔法方法:
    class MyClass(object):   # 先定义一个类
    
    • 双下init
        def __init__(self, name):
            self.name = name
              # 实例化对象的时候自动触发
    
    • 双下str
        def __str__(self):
            return '对象:%s'%self.name
              # 对象被执行打印操作的时候会自动触发
              # 该方法必须返回一个字符串
              # 返回什么字符串打印对象之后就展示什么字符串
      
    
    • 双下call
        def __call__(self, *args, **kwargs):
            print('__call__方法')
            print(args)
            print(kwargs)
              # 对象加括号调用 自动触发该方法
    
    • 双下getattr
        def __getattr__(self, item):
             print('__getattr__', item)
             return '您想要获取的属性名:%s不存在'%item
              # 当对象获取一个不存在的属性名,自动触发
              # 该方法返回什么对象获取不存在的属性名就会得到什么
              # 形参item就是对象想要获取的不存在的属性名
    
    • 双下setattr
        def __setattr__(self, key, value):
            super().__setattr__(key, value)
              # 对象操作属性值的时候自动触发>>>:对象.属性名=属性值
    
    • 双下del
        def __del__(self):
            pass
              # 对象在被删除(主动 被动)的时候自动触发
    
    • 双下getattribute
        def __getattribute__(self, item):
            return super().__getattribute__(item)  # 简便写法
              # 对象获取属性的时候自动触发 无论这个属性存不存在
              # 当类中既有__getattr__又有__getattribute__的时候,只走后面。
    
    
    
    • 双下enter
        def __enter__(self):
            print('__enter__')
              # 对象被with语法执行的时候自动触发 该方法返回什么 as关键字后面的变量名就能得到什么
    
    • 双下exit
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('__exit__')
              # 对象被with语法执行并运行完with子代码之后,自动触发"""
    

元类介绍

  • 之前我们使用type来查看数据的数据类型
    • 我们查看到的只是数据类型所属的类,这是因为数据类型本质就是通过各个类产生对象
    • type查看的是产生当前对象的类是谁
    class MyClass:
        pass
    obj = MyClass()
    print(type(obj))           # 产生对象obj的类:<class '__main__.MyClass.MyClass'>
    print(type(MyClass))       # 产生对象MyClass的类<class 'type'>
    
  • 产生类的类就是元类

产生类的两种方式

  • 1.使用class关键字:
    class MyClass:
        pass
    
  • 2.利用元类type:
    type(类名,类的父类,类的名称空间)
    

元类的基本使用

  • 1.继承了type的类才可以称为元类
    class MyMetaClass(type):
        pass
    
  • 2.切换产生类的元类不能使用继承,要使用关键字metaclass声明
    class MyClass(metaclass=MyMetaClass):
        pass
    
  • 类中的__init__用于实例化对象
  • 元类中__init__用于实例化类

元类进阶

  • 元类可以控制类的产生过程也可以控制对象的产生过程
    • 1.对象加括号执行产生该对象类里面的双下call
    class MyMetaClass(type):
        def __call__(self, *args, **kwargs):
            print('__call__')
            if args:
                raise Exception('必须用关键字参数传参')
            super().__call__(*args, **kwargs)
    
    • 2.类加括号执行产生该类的元类里面的双下call
    class MyClass(metaclass=MyMetaClass):
        def __init__(self, name, age):
            self.name = name
            self.age = age
            print('__init__')
    
  • 实例化对象所有参数都必须采用关键字的形式
    obj = MyClass(18,180)
    
  • 高度定制对象的产生过程:操作元类里面的__call__
  • 高度定制类的产生过程:操作元类里的__init__

双下new方法

  • 产生类的步骤
    • 1.产生一个空对象
    • 2.自动触发__init__方法实例化对象
    • 3.返回实例化完成的对象
  • __new__方法专门用于产生空对象(外壳)
  • __init__方法专门用于给对象添加属性(内脏)