zoukankan      html  css  js  c++  java
  • 在python3.6下 发明一个类似python3.7 dataclass数据类,不用在 __init__中self.xx

    虽然我用3.6,但我在2.7转3.6时候,把3.3 3.4 3.5 3.6的变化都看了一次,虽然已经忘了哪些变化。同时也关注3.7 3.8的变化,3.7中就有1个数据类印象深刻,因为之前在定义这种类时候,我基本上是按照如下截图做的,self.xx。

    py 3.7数据类介绍

    数据类比字典和具名元祖都强大,规范更好,更容易补全,因为pycharm能自动补全,基本不会出现打错字母的情况。

    为什么不

    class A():

                 x = None

                y= None

    这样做呢,因为这样写的x和y都是类属性,不是实例属性,类在解释器是唯一的,类 属性也是唯一的,基本上要实现多实例互补干扰,必须使用实例化类后的多个对象,这样每个对象的实例属性才是互不干扰的。

    如果不想 

    class A():

       def __init__():

           self.x = None

           self.y = None

    每次定义数据类都要加个self,那么就应该发明一个数据类。

    选择元类实现是一个不错的选择。

    # -*- coding: utf-8 -*-
    # @Author  : ydf
    # @Time    : 2019/6/12 17:25
    import copy
    import json
    from app.utils_ydf import simple_logger
    
    
    class DataMetaclass(type):
    
    
        def __call__(self, *args, **kwargs):
            instance = super().__call__(*args, **kwargs)
            instance.__dict__ = copy.deepcopy({k: v for k, v in self.__dict__.items() if not k.startswith('__')})   # 类属性天然自带其他几个__的属性。
            return instance
    
    
    class DataClassBase(metaclass=DataMetaclass):
        def get_dict(self):
            return self.__dict__
    
        def get_json(self):
            return json.dumps(self.__dict__)
    
        def __str__(self):
            return f"{self.__class__}    {json.dumps(self.__dict__)}"
    
    
    if __name__ == '__main__':
        # 实例属性和类属性隔离。
    
        class ShopItem(DataClassBase):
            a = 1
    
        shop_item = ShopItem()
        shop_item.a = 2
        simple_logger.debug(shop_item)
    
        shop_item = ShopItem()
        simple_logger.debug(shop_item)
        shop_item.a = 3
        simple_logger.debug(shop_item)
    
        simple_logger.debug(ShopItem.a)
    
        # print(shop_item.__dict__)

    这样就达到效果了。既不用写self,但又做到了类属性和各对象实例属性的隔离。

    使用元类时候,定义元类里面的self,self代表的是类,和普通的类创建对象,self指的是改类的对象不一样。所以思维要降维。

    元类一般来说是用来控制创建类的行为,写__new__ 写 __init__改变(增加)类的属性和方法,但要改变该类实例化的对象的创建行为,那就要使用__call__了,元类的__call__,就改变了普通类的__new__,思维要降维,元类是创建类的类,普通类是创建对象的类。实例的类型是类名,类的类名是type。

    用元类小题大做了吗。也可以使用装饰器来装饰类来实现数据类,装饰器不光可以装饰在函数上,也可以装饰在类上的。

  • 相关阅读:
    获取本地计算机的主机信息
    用函数SendARP()获取局域网计算机的MAC地址
    获取本地计算机的操作系统
    获取本地计算机名和IP地址
    基于TCP(面向连接)的Socket编程
    SMTP协议
    使用截获消息响应截断某些消息
    《Windows核心编程》读书笔记 上
    vc++高级班之多线程篇[7]---线程间的同步机制②
    vc++高级班之多线程篇[6]---线程间的同步机制①
  • 原文地址:https://www.cnblogs.com/ydf0509/p/11048228.html
Copyright © 2011-2022 走看看