面向对象之魔法方法

面向对象之魔法方法

  • 类的常用魔法方法如下
序号 双下方法 触发条件
1 init 对象添加独有数据的时候自动触发
2 str 对象被执行打印操作的时候自动触发
3 call 对象加括号调用的时候自动触发
4 getattr 访问对象不存在的属性时自动触发
5 getattribute 只要访问对象的名字就会触发(不常用)
6 setattr 给对象添加或者修改数据的时候自动触发
7 enter 当对象被当做with上下文管理操作的开始自动触发
8 exit 与enter相反,在上下文管理结束时触发
  • 魔法方法对应的代码实操
1. __init__

class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age


obj = A('almira', 24)
print(obj.__dict__)  # {'name': 'almira', 'age': 24}


2. __str__

class A:
    def __str__(self):
        return '我是类AB'


obj = A()
print(obj)  # 我是类AB

3.__call__

class A:
    cid = 99999  # 定义一个类里面的共有数据属性

    def __call__(self, *args, **kwargs):
        print(self)  # 可以 接受调用的对象本身
        print(args, kwargs)  # 可以接受参数
        return self.cid  # 返回一个返回值


obj = A()  # 类名加括号让变量接受就是产生对象的过程
print(obj(77, 88, name='almira'))  # 当对象被括号调用时自动出发
4.__getattr__

class A:
    cid = 99999

    def __getattr__(self, item):
        return f'没有{item}这个属性'


obj = A()
print(obj.cid)  # 99999
print(obj.ciddd)  # 没有ciddd这个属性
5. __getattribute__

class A:

    def __getattribute__(self, item):
        return '你以为你是谁???'


obj = A()
print(obj.cid)  # 你以为你是谁???
print(obj.cccid)  # 你以为你是谁???
6. __setattr__

class A:
    def __init__(self, name):
        self.name = name

    def __setattr__(self, key, value):
        print('__setattr__')
        print(key, value)


obj = A()  
print(obj)
7. ___enter__ & 8. __exit__

class A:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print('enter')
        return 123

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')
        return 234


a = A()
with a as f:
    print(f) 
  • 魔法方法相关笔试题
     1.补全下列代码使得运行不报错即可
        class Context:
            pass
        with Context() as f:
            f.do_something()
     
    class Context:
        def do_something(self):
            pass
        def __enter__(self):
            return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            pass
    with Context() as f:
        f.do_something()
        
    2.自定义字典类型并让字典能够通过句点符的方式操作键值对
    	class MyDict(dict):
            def __setattr__(self, key, value):
                self[key] = value
    
            def __getattr__(self, item):
                return self.get(item)
            obj = MyDict()
            obj.name = 'jason'
            obj.pwd = 18
            obj.hobby = 'read'
            # print(obj)
            print(obj.name)
            print(obj.pwd)
            print(obj.hobby)
            # print(obj)
            # print(obj)  # 字典存储的数据  {}
            # print(obj.__dict__)  # 字典对象名称空间  {'name': 'jason'}
    
            print(type(obj))
    
  • 元类以及创建元类
    1.元类的定义
    #定义的类其实是type产生的,所以我们把产生类的类(type)叫做元类
    
    2.创建元类的两种方式
    #方式一:通过关键字class创建
    class Student:
        name = 'almira'
        age = 24
    
    
    obj = Student()
    print(obj.name, obj.age)
    print(Student.__dict__)
    
    #方式二:通过关键字type创建
    # 语法结构:type(类名,类的父类,类的名称空间)
    cls = type('Student', (object,), {'name': 'almira'})
    print(cls)
    print(cls.__dict__)
    
    """
    了解知识:名称空间的产生
    1.手动写键值对
        针对绑定方法不好定义
    2.内置方法exec
        能够运行字符串类型的代码并产生名称空间
    """
    
    • 魔法方法之双下new
      class MyMetaclass(type):
          def __call__(self, *args, **kwargs):
              obj = self.__new__(self)  # 1.产生一个空对象(骨架)
              self.__init__(obj, *args, **kwargs)  # 2.调用__init__给对象添加独有的数据(血肉)
      
              return obj  # 3.返回创建好的对象
      
      
      class Student(metaclass=MyMetaclass):
          def __init__(self, name):
              self.name = name
      
      
      obj = Student('almira')
      print(obj.name)
      
posted @ 2022-11-08 21:26  阿丽米热  阅读(17)  评论(0编辑  收藏  举报
Title