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

 

py 3.7數據類介紹app

 

數據類比字典和具名元祖都強大,規範更好,更容易補全,由於pycharm能自動補全,基本不會出現打錯字母的狀況。函數

 

爲何不spa

class A():debug

             x = Nonecode

            y= None對象

這樣作呢,由於這樣寫的x和y都是類屬性,不是實例屬性,類在解釋器是惟一的,類 屬性也是惟一的,基本上要實現多實例互補干擾,必須使用實例化類後的多個對象,這樣每一個對象的實例屬性纔是互不干擾的。blog

 

若是不想 utf-8

class A():get

   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。

 

用元類小題大作了嗎。也可使用裝飾器來裝飾類來實現數據類,裝飾器不光能夠裝飾在函數上,也能夠裝飾在類上的。

相關文章
相關標籤/搜索