Python元类编程

前言

在面向对象编程中有个难点,元类,本章总结下元类的定义和使用以及详细的对象实例化过程


章节一、实例化对象

一句话描述: 元类的实例化对象是类对象, 类的实例化对象是实例对象

1. __new__的参数
  • __new__(cls, *args, **kwargs) 在实例化对象时,Python解释器自动将该类当做第 一个参数传入cls, 然后其他参数则按照入参规则传入 argskwargs, 而后解释器又将 __new__的返回值及 args, kwargs 作为参数传入 __init__, 即: __new__ 跟的参数除了cls其他由 __init__决定(元类的除外, 参考章节三)
    class A:
    	def __new__(cls, *args, **kwargs):
    		print(f'当前类 {cls} 参数 args {args}, kwargs {kwargs}')
    		return super().__new__(cls)
        def __init__(self, *args, **kwargs):
            print(f'当前类 {self} 参数 args {args}, kwargs {kwargs}')
    
    >>> A(1, 2, 3, a=6)
    当前类 <class '__main__.A'> 参数 args (1, 2, 3), kwargs {'a': 6}
    当前实例 <__main__.A object at 0x0000000001DD4978> 参数 args (1, 2, 3), kwargs {'a': 6}
    
2. __new__的返回值
  • __new__的返回值必须是自己的实例或者object.__new__(cls), 否则内部调用将会出现混乱, 用一个例子说明下类的创建及初始化过程
  • 示例
    class B(object):
        def __new__(cls, *args, **kwargs):
            print('------B __new__----------')
            return object.__new__(cls)
    
        def __init__(self):
            print('--------B 的 __init__-----------')
    	
    
    class A(B):
    
        def __new__(cls, *args, **kwargs):
            instance = B.__new__(cls)
    
            return instance
    
        def __init__(self):
            super().__init__()
            print(f'__init__:: {self} A的 __init__')
    
        def __call__(self, *args, **kwargs):
            print('__call__:: A.__call__')
    
    >>> A()
    
    
    
3. 引自官网
  • 调用来创建类cls的新实例。new()是一个静态方法(特殊大小写,所以不需要这样声明),它将实例被请求的类作为其第一个参数。剩下的参数是那些传递的参数
  • 如果__new__()返回一个cls实例,则新实例的__init__()方法将像__init__(self[,…])一样被调用,其中self为新实例,其余参数与传递给__new__()的参数相同。
  • 如果__new__()不返回cls的实例,则新实例的__init__()方法将不会被调用。
  • new()主要用于允许不可变类型(如int、str或tuple)的子类自定义实例创建。在自定义元类中也通常重写它,以自定义类的创建。
4. __new__和__init__的区别
  • __new__(cls, [...])负责对象的创建 返回值是: 实例化出来的实例, 实例对象创建完成后调用__init__(self, [...]) 方法, 传入的第一个参数就是 __new__ 返回的实例对象,这一切的调用是有Python解释器自动完成的,总之, __new__负责对象的创建,__init__负责对象的一些初始化操作, 两个共同构成了类的构造器
5. 常用场景-单例模式
  • class A:
    	_instance = None
    	def __new__(cls, *args, **kwargs):
    		if not cls._instance:
    			cls._instance = super().__new__(cls, *args, **kwargs)
    		return cls._instance
    
    

章节二、type

1. 是什么?
  • 是实例化类的类, 即 元类
    class type(object):
        """
        type(object) -> the object's type
        type(name, bases, dict) -> a new type
        """
    	...
        def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
           """
           type(object) -> the object's type
           type(name, bases, dict) -> a new type
           # (copied from class doc)
           """
           pass
    
    可以看到用法为:
    type(object) -> the object’s type: 入参对象, 返参对象类型
    type(name, bases, dict) -> a new type: 入参分别为 类的名称, 基类元组, 属性字典, 返参为一个新的
2. 作用
  • 1.判断对象类型
    >>> type(1)
    <type 'int'>
    >>> 
    
  • 2.动态创建类
    def fun(self):
    	print(f'the instance {self}, fun demo')
    ClassObj = type('ClassObj', (object, ), {"a": 1, "fun": fun})
    >>> ClassObj().fun()
    the instance <__main__.ClassObj object at 0x7feb0e909850>, fun demo
    >>> ClassObj.__name__ 
    'ClassObj'
    >>>
    
    以上的定义方式等同于
    class ClassObj(object):
    	a = 1
    	def fun(self):
    		print(f'the instance {self}, fun demo')
    

在Python解析器解析到class语句的时候会对语句后面的部分做type的实例化操作, 可以根据这个特性做一些定制化的操作,如单例模式, ``


章节三、metaclass(元类)

知道了type的作用,那可以通过自定义元类来实现用户自定义的操作

1. 自定义元类
  • code
    class Metaclass(type):
        def __new__(mcs, class_name, base_class, class_attr):
            assert isinstance(base_class, tuple)
            print(f'元类 {mcs}, 参数 class_name={class_name}; base_class={base_class}; class_attr={class_attr}')
            return type.__new__(mcs, class_name, base_class, class_attr)
    
    
    class A(object, metaclass=Metaclass):
        pass
    
    >>>
    元类 <class '__main__.Metaclass'>, 参数 class_name=A; base_class=(<class 'object'>,); class_attr={'__module__': '__main__', '__qualname__': 'A'}
    
2. 元类使用 - 单例模式
  • code
    class MetaClass(type):
        def __call__(cls, *args, **kwargs):
            instance = getattr(cls, "instance", None)
            if instance is None:
                instance = super().__call__(*args, **kwargs)
                setattr(cls, "instance", instance)
            return instance
    
    
    class A(metaclass=MetaClass):
        def __init__(self, *args, **kwargs):
            print(f"args={args}, kwargs={kwargs}")
    
3. 元类使用 - ORM

4. __init_subclass__定义子类行为

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值