最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)易的ORM模型

 更新時(shí)間:2021年05月12日 16:44:58   作者:大渝  
ORM(Object Relational Mapping)是一種程序設(shè)計(jì)技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。本文將介紹如何使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)易的ORM

本文記錄下自己使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)易的ORM模型

使用到的知識(shí)

1、元類

2、描述器

元類

對(duì)于元類,我的理解其實(shí)也便較淺,大概是這個(gè)意思

所有的類都是使用元類來進(jìn)行創(chuàng)建的,而所有的類的父類中必然是object(針對(duì)Python3),Python中的元類只有一個(gè)(type),當(dāng)然這里不包含自定義元類

下面我們來看下類的創(chuàng)建

class Test:   # 定義一個(gè)類
    pass

Test1 = type("Test2",(object,),{"name":"test"})  # 定義一個(gè)類


print(type(Test))
print(type(Test1))-----------------------
<class 'type'><class 'type'>

從上面可以看出創(chuàng)建類,其實(shí)是有兩種方式,一種是通過class關(guān)鍵字來定義,一種是通過type來進(jìn)行創(chuàng)建,當(dāng)然常用的是使用class來進(jìn)行創(chuàng)建了,在看最后的結(jié)果,可以看出類的類型為type。說明我們這個(gè)類就是由type來創(chuàng)建的

明白了這個(gè)之后我們?cè)賮硎崂硐略趺词褂米远x元類來創(chuàng)建類,明白一點(diǎn),自定義元類需要繼承type

class MetaClass(type):  # 定義一個(gè)元類
    pass


class Test(metaclass=MetaClass):  # 使用自定義元類來創(chuàng)建類
    pass



print(type(Test))


--------------------------

<class '__main__.MetaClass'>

很明顯可以看出Test類就是用MetaClass類創(chuàng)建出來的

描述器

從描述器的定義來說,只要一個(gè)類中實(shí)現(xiàn)了__get__、__set__、__delete__中的一個(gè)或幾個(gè),這個(gè)類的實(shí)例就可以叫描述器

下面我們來定義一個(gè)簡(jiǎn)易的描述器

class Describer:

    def __set__(self, instance, value):
        print("設(shè)置屬性的時(shí)候會(huì)被調(diào)用")
        self.value = value

    def __get__(self, instance, owner):
        print("獲取屬性的時(shí)候會(huì)被調(diào)用")
        return self.value

    def __delete__(self, instance):
        print("刪除屬性的時(shí)候會(huì)被調(diào)用")
        self.value = None


class Test:
    name = Describer()



t = Test()
t.name = "xxxxx"
print(t.name)

----------------------

設(shè)置屬性的時(shí)候會(huì)被調(diào)用
獲取屬性的時(shí)候會(huì)被調(diào)用
xxxxx

從上面的代碼中有沒有什么想法?既然__set__方法會(huì)在我們?cè)O(shè)置屬性的時(shí)候會(huì)被調(diào)用,那么我們是不是可以在設(shè)置屬性前對(duì)這個(gè)屬性做一些操作呢?

ORM模型

ORM模型到底是個(gè)啥?ORM對(duì)于后端研發(fā)來說肯定是不陌生的,包括很多后端框架現(xiàn)在都自帶這個(gè)模型了

ORM(Object Relational Mapping)對(duì)象關(guān)系映射

既然是對(duì)象關(guān)系映射,那對(duì)象是啥?我的理解為:Python中的類與數(shù)據(jù)庫之間的映射,對(duì)數(shù)據(jù)的操作就不用編寫SQL語言了,因?yàn)槎挤庋b好了,比如你想插入一條數(shù)據(jù),你就直接創(chuàng)建一個(gè)對(duì)象即可,

Python ------->>>>      數(shù)據(jù)庫

類名     ------->>>>      數(shù)據(jù)庫中的表名

對(duì)象     ------->>>>      數(shù)據(jù)庫中的一行數(shù)據(jù)

屬性     ------->>>>      數(shù)據(jù)庫中的字段

大致就是上面的映射關(guān)系

ORM實(shí)現(xiàn)步驟

1、利用描述器實(shí)現(xiàn)對(duì)數(shù)據(jù)庫字段的類型、長度限制

2、實(shí)現(xiàn)Mode類,也就是Python中的類

3、利用元類實(shí)現(xiàn)映射關(guān)系

好,我們先利用描述器來實(shí)現(xiàn)對(duì)數(shù)據(jù)字段的類型,長度限制

class BaseFiled:
    pass


class CharFiled(BaseFiled):
    """定義一個(gè)字符串的類型限制"""

    def __init__(self, length=10):
        self.length = length

    def __set__(self, instance, value):
        if isinstance(value, str):
            if len(value) <= self.length:
                self.value = value
            else:
                raise ValueError("length can not exceed {}".format(self.length))
        else:
            raise TypeError("need a str")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None


class IntFiled(BaseFiled):
    """定義一個(gè)數(shù)值的類型限制"""

    def __set__(self, instance, value):
        if isinstance(value, int):

            self.value = value
        else:
            raise TypeError("need a int")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None


class BoolFiled(BaseFiled):
    """定義一個(gè)布爾的類型限制"""
    def __set__(self, instance, value):
        if isinstance(value, bool):

            self.value = value
        else:
            raise TypeError("need a bool")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None

上面實(shí)現(xiàn)了三種,分別是字符串、數(shù)值、布爾值的,下面在來實(shí)現(xiàn)元類以及模型類

class MyMateClass(type):
    """自定義一個(gè)元類"""
    def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):
        """

        :param name: name為模型類的類名也就是數(shù)據(jù)庫中的表名
        :param bases:  bases為一個(gè)元祖類型,里面裝的是name這個(gè)類的父類
        :param dic: dic為一個(gè)dict類型,裝的是name這個(gè)類中的屬性
        :param args:
        :param kwargs:
        :return:
        """
        if name == "BaseMode":   # 判斷類名是否為BaseMode,如果是則直接使用元類創(chuàng)建類,不做其他任何操作
            return super().__new__(cls, name, bases, dic)
        else:
            table_name = name.lower()  # 將表名變成小寫
            filed_dic = {}   # 定義一個(gè)空的列表,用來裝dic中屬于BaseFiled類型的屬性,因?yàn)閐ic中會(huì)有其他創(chuàng)建類時(shí)自動(dòng)生成的屬性,這些屬性我們沒必要去建立映射關(guān)系,所以需要將其剔除掉
            for k, v in dic.items():
                if isinstance(v, BaseFiled):
                    filed_dic[k] = v
            dic["t_name"] = table_name    # 將表名添加到dic中,實(shí)現(xiàn)類名與表名的映射關(guān)系
            dic["filed_dict"] = filed_dic  # 將屬于BaseFiled類型的屬性給添加到dic中,實(shí)現(xiàn)屬性與字段的映射關(guān)系
            return super().__new__(cls, name, bases, dic)


class BaseMode(metaclass=MyMateClass):

    def __init__(self, **kwargs):
        """
        由于每一個(gè)模型類(也就是數(shù)據(jù)庫表)的屬性個(gè)數(shù)不一致,所以我們需要定義一個(gè)父類來進(jìn)行定義初始化的屬性
        :param kwargs:
        """
        for k, v in kwargs.items():   # 遍歷傳進(jìn)來的所有屬性
            setattr(self, k, v)   # 拿到這些屬性后對(duì)self(也就是類本身)進(jìn)行設(shè)置屬性

    def save(self):
        """生成SQL語句"""
        # 獲取表名
        table_name = self.t_name
        # 獲取所有的屬性
        fileds = self.filed_dict
        dic = {}  # 定義一個(gè)空字典,用來裝屬性名和屬性值
        for k, v in fileds.items():
            value = getattr(self, k)
            dic[k] = value
        sql = "insert into {} values{}".format(table_name, tuple(dic.values()))
        return sql


class User(BaseMode):
    name = CharFiled()
    age = IntFiled()
    love = CharFiled(length=50)
    live = BoolFiled()


if __name__ == '__main__':
    c = User(name="lc", age=12, love="hjh", live=True)
    c.save()




--------------------------
insert into user values('lc', 12, 'hjh', True)

以上就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的ORM模型了,這個(gè)雖然在測(cè)試開發(fā)過程中用的很少(一般都是直接用框架中封裝好的),學(xué)習(xí)這個(gè)也是為了更好的理解原理,后面好學(xué)習(xí)flask以及Django。

下面貼一下完整的代碼吧

# -*- coding: utf-8 -*-
# @Time    : 2021-05-11 10:14
# @Author  : cainiao
# @File    : Meat.py
# @Software: PyCharm
# @Content : 實(shí)現(xiàn)ORM模型

class BaseFiled:
    pass


class CharFiled(BaseFiled):
    """定義一個(gè)字符串的類型限制"""

    def __init__(self, length=10):
        self.length = length

    def __set__(self, instance, value):
        if isinstance(value, str):
            if len(value) <= self.length:
                self.value = value
            else:
                raise ValueError("length can not exceed {}".format(self.length))
        else:
            raise TypeError("need a str")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None


class IntFiled(BaseFiled):
    """定義一個(gè)數(shù)值的類型限制"""

    def __set__(self, instance, value):
        if isinstance(value, int):

            self.value = value
        else:
            raise TypeError("need a int")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None


class BoolFiled(BaseFiled):
    """定義一個(gè)數(shù)值的類型限制"""

    def __set__(self, instance, value):
        if isinstance(value, bool):

            self.value = value
        else:
            raise TypeError("need a bool")

    def __get__(self, instance, owner):
        return self.value

    def __delete__(self, instance):
        self.value = None


class MyMateClass(type):
    """自定義一個(gè)元類"""
    def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):
        """

        :param name: name為模型類的類名也就是數(shù)據(jù)庫中的表名
        :param bases:  bases為一個(gè)元祖類型,里面裝的是name這個(gè)類的父類
        :param dic: dic為一個(gè)dict類型,裝的是name這個(gè)類中的屬性
        :param args:
        :param kwargs:
        :return:
        """
        if name == "BaseMode":   # 判斷類名是否為BaseMode,如果是則直接使用元類創(chuàng)建類,不做其他任何操作
            return super().__new__(cls, name, bases, dic)
        else:
            table_name = name.lower()  # 將表名變成小寫
            filed_dic = {}   # 定義一個(gè)空的列表,用來裝dic中屬于BaseFiled類型的屬性,因?yàn)閐ic中會(huì)有其他創(chuàng)建類時(shí)自動(dòng)生成的屬性,這些屬性我們沒必要去建立映射關(guān)系,所以需要將其剔除掉
            for k, v in dic.items():
                if isinstance(v, BaseFiled):
                    filed_dic[k] = v
            dic["t_name"] = table_name    # 將表名添加到dic中,實(shí)現(xiàn)類名與表名的映射關(guān)系
            dic["filed_dict"] = filed_dic  # 將屬于BaseFiled類型的屬性給添加到dic中,實(shí)現(xiàn)屬性與字段的映射關(guān)系
            return super().__new__(cls, name, bases, dic)


class BaseMode(metaclass=MyMateClass):

    def __init__(self, **kwargs):
        """
        由于每一個(gè)模型類(也就是數(shù)據(jù)庫表)的屬性個(gè)數(shù)不一致,所以我們需要定義一個(gè)父類來進(jìn)行定義初始化的屬性
        :param kwargs:
        """
        for k, v in kwargs.items():   # 遍歷傳進(jìn)來的所有屬性
            setattr(self, k, v)   # 拿到這些屬性后對(duì)self(也就是類本身)進(jìn)行設(shè)置屬性

    def save(self):
        """生成SQL語句"""
        # 獲取表名
        table_name = self.t_name
        # 獲取所有的屬性
        fileds = self.filed_dict
        dic = {}  # 定義一個(gè)空字典,用來裝屬性名和屬性值
        for k, v in fileds.items():
            value = getattr(self, k)
            dic[k] = value
        sql = "insert into {} values{}".format(table_name, tuple(dic.values()))
        return sql


class User(BaseMode):
    name = CharFiled()
    age = IntFiled()
    love = CharFiled(length=50)
    live = BoolFiled()


if __name__ == '__main__':
    c = User(name="lc", age=12, love="hjh", live=True)
    print(c.save())
    # c.name="lc"
    # print(c.name)

以上就是如何使用Python實(shí)現(xiàn)一個(gè)簡(jiǎn)易的ORM模型的詳細(xì)內(nèi)容,更多關(guān)于python 實(shí)現(xiàn)ORM模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python基于高斯消元法計(jì)算線性方程組示例

    Python基于高斯消元法計(jì)算線性方程組示例

    這篇文章主要介紹了Python基于高斯消元法計(jì)算線性方程組,結(jié)合實(shí)例形式分析了Python高斯消元法針對(duì)方程組求解的相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • python 進(jìn)程 進(jìn)程池 進(jìn)程間通信實(shí)現(xiàn)解析

    python 進(jìn)程 進(jìn)程池 進(jìn)程間通信實(shí)現(xiàn)解析

    這篇文章主要介紹了python 進(jìn)程 進(jìn)程池 進(jìn)程間通信實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Linux下遠(yuǎn)程連接Jupyter+pyspark部署教程

    Linux下遠(yuǎn)程連接Jupyter+pyspark部署教程

    這篇文章主要為大家詳細(xì)介紹了Linux下遠(yuǎn)程連接Jupyter+pyspark部署教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • python next()和iter()函數(shù)原理解析

    python next()和iter()函數(shù)原理解析

    這篇文章主要介紹了python next()和iter()函數(shù)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 使用python Telnet遠(yuǎn)程登錄執(zhí)行程序的方法

    使用python Telnet遠(yuǎn)程登錄執(zhí)行程序的方法

    今天小編就為大家分享一篇使用python Telnet遠(yuǎn)程登錄執(zhí)行程序的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python pygame實(shí)現(xiàn)五子棋小游戲

    python pygame實(shí)現(xiàn)五子棋小游戲

    這篇文章主要為大家詳細(xì)介紹了python pygame實(shí)現(xiàn)五子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Python的裝飾器使用詳解

    Python的裝飾器使用詳解

    最近在學(xué)習(xí)python,下面是在Python學(xué)習(xí)小組上介紹的內(nèi)容,現(xiàn)學(xué)現(xiàn)賣、多練習(xí)是好的學(xué)習(xí)方式,希望大家能夠喜歡
    2017-06-06
  • Python中collections模塊的基本使用教程

    Python中collections模塊的基本使用教程

    collections是Python內(nèi)建的一個(gè)集合模塊,提供了許多有用的集合類。下面這篇文章主要給大家介紹了關(guān)于Python中collections模塊的基本使用,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-12-12
  • 簡(jiǎn)單談?wù)凱ython中的json與pickle

    簡(jiǎn)單談?wù)凱ython中的json與pickle

    下面小編就為大家?guī)硪黄?jiǎn)單談?wù)凱ython中的json與pickle。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • 淺談Python3 numpy.ptp()最大值與最小值的差

    淺談Python3 numpy.ptp()最大值與最小值的差

    今天小編就為大家分享一篇淺談Python3 numpy.ptp()最大值與最小值的差,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08

最新評(píng)論

双江| 海阳市| 乡城县| 砀山县| 庄浪县| 英德市| 铜鼓县| 开化县| 巫山县| 永寿县| 铜山县| 宁陕县| 娄烦县| 札达县| 平度市| 浦城县| 白朗县| 田林县| 敦化市| 双柏县| 孟村| 区。| 汉寿县| 新巴尔虎右旗| 南靖县| 桃江县| 纳雍县| 裕民县| 象山县| 彩票| 都江堰市| 车险| 桃源县| 金山区| 台安县| 南和县| 阜城县| 寿阳县| 梁河县| 清新县| 牙克石市|