在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。

 

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

 

posted @ 2019-06-21 09:22  北风之神0509  阅读(485)  评论(0编辑  收藏  举报