首页 > 其他分享 >面向对象的魔法方法与元类

面向对象的魔法方法与元类

时间:2022-11-08 19:46:23浏览次数:52  
标签:__ obj name self 魔法 元类 面向对象 print def

面向对象的魔法方法与元类

面向对象的魔法方法

魔法方法就是在类中定义的双下方法,它不需要人为调用,在特定的条件下会自动触发运行
1. __init__  对象添加独有数据的时候会自动触发
    class A:
    def __init__(self, name):
        print(name)
    obj = A('zyg')  # zyg
    
2. __str__  对象被执行打印操作的时候会自动触发
    class A:
    def __init__(self, name):
        print(name)

    def __str__(self):
        print('__str__')
    obj = A('zyg')  # zyg
    print(obj)  # __str__

3. __call__  对象加括号调用的时候自动触发
    class A:
    def __init__(self, name):
        print(name)

    def __call__(self, *args, **kwargs):
        print('__call__')
    obj = A('zyg')  # zyg
    obj()  # __call__
    
4. __getattr__  对象点不存在的名字时自动触发
    class A:
    def __init__(self, name):
        self.name = name

    def __getattr__(self, item):
        print('__getattr__')
    obj = A('zyg')  # zyg
    obj.age  # __getattr__
    
5. __getattribute__  对象点名字就会触发,无论名字是否存在,与__getattr__同时存在时只会执行他自己
    class A:
    def __init__(self, name):
        self.name = name

    def __getattr__(self, item):
        print('__getattr__')
    def __getattribute__(self, item):
        print('__getattribute__')
    obj = A('zyg')  # zyg
    obj.name  # __getattribute__
    obj.age  # __getattribute__
    
6. __setattr__  给对象添加或者修改数据的时候自动触发
    class A:
    def __init__(self, name):
        self.name = name
    def __setattr__(self, key, value):
        print('__setattr__')
    obj = A('zyg')  # __setattr__
    obj.name = 'json'  # __setattr__
    
7. __enter__  
当对象被当做with上下文管理操作的开始自动触发 并且该方法返回什么 as后面的变量名就会接收到什么
   __exit__  with上下文管理语法运行完毕之后自动触发(子代码结束)
  # __enter__与__exit__必须一起使用,单独使用会报错
    class A:
    def __init__(self, name):
        self.name = name
    def __enter__(self):
        return '__enter__'
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')
    obj = A('zyg')
    with obj as f:
        print(f)
   # __enter__
   # __exit__

魔法方法笔试题

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:  # Context() 产生对象  f获得__enter__方法的返回值,即f等同于Context()产生的对象
        f.do_something()  # 对象点方法,增加一个方法即可
    
2.自定义字典类型并让字典能够通过句点符的方式操作键值对
    class MyDict(dict):  # 定义子类继承字典,该类产生的对象是一个空字典,如果对象直接使用点名字的方法来添加数据,添加的是对象的名称空间,字典内没有数据
   
        def __setattr__(self, key, value):  # 对象调用时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)  # {'name': 'jason', 'pwd': 18, 'hobby': 'read'}
        print(obj.name)
        print(obj.pwd)
        print(obj.hobby)
        print(type(obj))  # <class '__main__.MyDict'>

元类简介

元类简单来说就是产生类的类
python中一切皆对象,我们在查看字符串str、列表list、字典dict、元组tuple的数据类型时用的都是type,那么我们可以测试一下type也是查看产生对象的类名的
    class A:
        pass
    obj = A()
    print(type(obj))  # <class '__main__.A'>
由此可见type可以查看产生对象的类名,那能不能查看类
    class A:
        pass
    print(A)  # <class 'type'>
用type查看type会发生什么?
    print(type(type))  # <class 'type'>
由此我们可以得出结论:我们定义的类都是有type类产生的,也就是说type为元类

创建类的两种方式

方式一:使用关键字class
方式二:使用元类type type(类名,父类,类的名称空间)
    obj = type('A', (object,), {'name': 'jason'})
    print(obj)  # <class '__main__.A'>
    print(obj.__dict__)  # {'name': 'jason', '__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}

元类定制类的产生行为

类是由元类产生的,那么我们可以在元类产生类的时候做一些条件限制,这种类就叫做元类定制类
eg:规定所有的类名都必须首字母大写,否则无法产生、
    第一步:自定义元类,能继承type的类也称之为元类
    class MyMetaClass(type):
        def __init__(self, what, bases=None, dict=None):
            
            print('what', what)  # 传入参数为类名
            print('bases', bases)  # ()元组
            print('dict', dict)  # 字典  名称空间
            if not what.istitle():
                raise TypeError('你是不是python程序员 懂不懂规矩 类名首字母应该大写啊!!!')
            super().__init__(what, bases, dict)
    第二步:指定类的元类,利用关键字metaclass指定类的元类
    class myclass(metaclass=MyMetaClass):  # 类名全小写,会抛出异常
        desc = '元类其实很有趣 就是有点绕'

    class Student(metaclass=MyMetaClass):  # 类名首字母大写,正常执行
        info = '我是学生 我很听话'
    print(Student)  
    print(Student.__dict__)    
    

元类定制对象的产生行为

通过元类定制类产生的对象
eg:给对象添加独有数据的时候 必须采用关键字参数传参
    class MyMetaClass(type):
    def __call__(self, *args, **kwargs):  # args接收位置参数,kwargs接收关键字参数
        # 1.产生一个空对象(骨架)
        # 2.调用__init__给对象添加独有的数据(血肉)
        # 3.返回创建好的对象
        # print(args)  # ('jason', 18, 'male')
        # print(kwargs)  # {}
        if args:  # 只需要判断args是否有值就可以判断是位置参数传参还是关键字
            raise TypeError("对象的独有数据必须按照关键字参数传参!")
        return super().__call__(*args, **kwargs)
    
    class Student(metaclass=MyMetaClass):
        def __init__(self, name, age, gender):
            # print('__init__')
            self.name = name
            self.age = age
            self.gender = gender
            
    # obj = Student('jason', 18, 'male')  # 报错
    obj = Student(name='jason',age= 18,gender= 'male')
    print(obj.__dict__)

魔法方法值双下new

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        # 1.产生一个空对象(骨架)
        obj = self.__new__(self)
        # 2.调用__init__给对象添加独有的数据(血肉)
        self.__init__(obj,*args, **kwargs)
        # 3.返回创建好的对象
        return obj


class Student(metaclass=MyMetaClass):
    def __init__(self, name):
        self.name = name

obj = Student('jason')
print(obj.name)
"""
__new__可以产生空对象
"""

标签:__,obj,name,self,魔法,元类,面向对象,print,def
From: https://www.cnblogs.com/zyg111/p/16870910.html

相关文章

  • 元类、魔法方法(魔术方法)
    目录今日内容概要今日内容详细面向对象的魔法方法魔法方法笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new设计模式简介作业......
  • 面向对象魔法方法及元类
    内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new方法设......
  • 面向对象的魔法方法、魔法方法笔试题、元类简介、创建类的两种方式、元类定制类的产生
    面向对象的魔法方法魔法方法:类中定义的双下方法都称为魔法方法 不需要人为调用在特定的条件下回自动触发运行 eg:__init__创建空对象之后自动触发给对象添加独有的数......
  • 面向对象编程(四)
    面向对象编程(四)一、面向对象的魔法方法1.魔法方法简介在类中,有一些内置好的特定的方法,方法名是“__xx__”,在进行特定的操作时会被调用,这些方法被称为魔法方法,不需......
  • 面向对象之元类、魔法方法
    今日内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为袁磊定制对象的产生行为魔法方法之双侠new方法设计模式简......
  • 面向对象的魔法方法、元类
    目录一、面向对象的魔法方法1.魔法方法介绍(1)__init__(2)__str__(3)__call__(4)__getattr__(5)__getattribute__(6)__setattr__(7)__enter__(8)__exit__(9)__del__2.魔法方法笔试题1)补全下列......
  • python(面向对象之元类,魔法方法)
    今日内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法之__new__方法设计模式简介及单......
  • 魔法方法
    目录面向对象魔法方法__init____str____call____getattr____getattribute____setattr____enter____exit__魔法方法笔试题元类推导流程创建类的两种方式class关键字使用......
  • Python基础之面向对象:7、面向对象之魔法方法
    目录面向对象之魔法方法一、魔法方法的概念二、常用魔法方法1、__init__2、__str__3、__call__4、__getattr__5、__getattribute__6、__setattr__7、__enter......
  • python 面向对象之元类
    python面向对象之元类type方法的应用1.查看数据类型s1='helloworld'#str()l1=[11,22,33,44]#list()d1={'name':'jason','pwd':123}#dict()t1......