欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python元類(lèi)編程實(shí)現(xiàn)一個(gè)簡(jiǎn)單的ORM

 更新時(shí)間:2023年03月05日 09:24:14   作者:代碼輸入中...  
本文主要介紹了Python元類(lèi)編程實(shí)現(xiàn)一個(gè)簡(jiǎn)單的ORM,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

概述

什么是ORM?   

ORM全稱(chēng)“Object Relational Mapping”,即對(duì)象-關(guān)系映射,就是把關(guān)系數(shù)據(jù)庫(kù)的一行映射為一個(gè)對(duì)象,也就是一個(gè)類(lèi)對(duì)應(yīng)一個(gè)表,這樣,寫(xiě)代碼更簡(jiǎn)單,不用直接操作SQL語(yǔ)句。

現(xiàn)在我們就要實(shí)現(xiàn)簡(jiǎn)易版ORM?!?/p>

效果

class Person(Model):
    """
    定義類(lèi)的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()

通過(guò)執(zhí)行save()方法 動(dòng)態(tài)生成sql插入語(yǔ)句, 是不是很神奇, 那我們現(xiàn)在開(kāi)始解析原理吧

步驟

首先我們要定義一個(gè) Field 類(lèi) 它負(fù)責(zé)保存數(shù)據(jù)庫(kù)表的字段名和字段類(lèi)型:

class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)

在 Field 的基礎(chǔ)上,進(jìn)一步定義各種類(lèi)型的 Field,比如 StringField,IntegerField 等等:

class StringField(Field):
    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(100)')
 
class IntegerField(Field):
    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'bigint')

下一步,就是編寫(xiě)最復(fù)雜的 ModelMetaclass:

class ModelMetaclass(type):
 
    def __new__(cls, name, bases, attrs):
        if name == "Model":
            return type.__new__(cls, name, bases, attrs)
        mappings = dict()
        print("Found class: %s" % name)
        for k, v in attrs.items():
            if isinstance(v, Field):
                print("Found mapping: %s ==> %s" % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs["__table__"] = name  # 表名和類(lèi)名一致
        attrs["__mappings__"] = mappings  # 保存屬性和列的映射關(guān)系
        return type.__new__(cls, name, bases, attrs)

最后就是基類(lèi)  Model:

class Model(metaclass=ModelMetaclass):
 
    def __init__(self, **kwargs):
        _setattr = setattr
        if kwargs:
            for k, v in kwargs.items():
                _setattr(self, k, v)
        super(Model, self).__init__()
 
    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(k)
            params.append("?")
            args.append(getattr(self, k, None))
        sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ",".join(params))
        print('插入語(yǔ)句: %s' % sql)
        print('參數(shù): %s' % str(args))
 
    def update(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            if getattr(self, k, None):
                fields.append(k+"=?")
                args.append(getattr(self, k, None))
        sql = "update %s set %s" % (self.__table__, ','.join(fields))
        print("更新語(yǔ)句: %s " % sql)
        print("參數(shù): %s" % args)
 
    def filter(self, *args):
        pass
 
    def delete(self):
        pass

當(dāng)用戶定義一個(gè) class Person(Model) 繼承父類(lèi)時(shí),Python解釋器會(huì)在當(dāng)前類(lèi) Person 的定義中找 __metaclass__,如果沒(méi)有找到,就繼續(xù)到父類(lèi)中找 __metaclass__,實(shí)在找不到就用默認(rèn) type 類(lèi)。

我們?cè)诟割?lèi) Model 中定義了 __metaclass__ 的 ModelMetaclass 來(lái)創(chuàng)建 Person 類(lèi),所以 metaclass 隱式地繼承到子類(lèi)。

在 ModelMetaclass 中,一共做了幾件事情:

  • 排除掉對(duì) Model 類(lèi)的修改;
  • 在當(dāng)前類(lèi)(比如 Person )中查找定義的類(lèi)的所有屬性,如果找到一個(gè) Field 屬性,就把它保存到一個(gè) __mappings__ 的dict中,同時(shí)從類(lèi)屬性中刪除該Field屬性,否則,容易造成運(yùn)行時(shí)錯(cuò)誤;
  • 把表名保存到 __table__ 中,這里簡(jiǎn)化為表名默認(rèn)為類(lèi)名。

在Model類(lèi)中,就可以定義各種操作數(shù)據(jù)庫(kù)的方法,比如save(),delete(),find(),update() 等等。

我們實(shí)現(xiàn)了save(), update()方法,把一個(gè)實(shí)例保存到數(shù)據(jù)庫(kù)中。因?yàn)橛斜砻?,屬性到字段的映射和屬性值的集合,就可以?gòu)造出INSERT語(yǔ)句和UPDATE語(yǔ)句。

編寫(xiě)代碼試試:

class UserInfo(Model):
    """
        定義類(lèi)的屬性到列的映射
    """
    uid = IntegerField('uid')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
 
class Person(Model):
    """
    定義類(lèi)的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()
u2 = UserInfo(password='123456')
u2.update()

輸出

Found class: UserInfo
Found mapping: uid ==> <IntegerField:uid>
Found mapping: name ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
Found class: Person
Found mapping: pid ==> <IntegerField:id>
Found mapping: names ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
插入語(yǔ)句: insert into Person (pid,names,email,password) values (?,?,?,?)
參數(shù): [10086, '曉明', '10086@163.com', '123456']
更新語(yǔ)句: update UserInfo set password=? 
參數(shù): ['123456']

結(jié)束語(yǔ)

就這樣一個(gè)小巧的ORM就這么完成了。是不是學(xué)到了很多呢 ?這里利用的是元編程,很多Python框架都運(yùn)用了元編程達(dá)到動(dòng)態(tài)操作類(lèi)。

注:上述代碼列子 結(jié)合了廖雪峰的列子和少量的django ORM源碼。

完整代碼

class Field(object):
    def __init__(self, name, column_type):
        self.name = name
        self.column_type = column_type
 
    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)
 
 
class StringField(Field):
    def __init__(self, name):
        super(StringField, self).__init__(name, 'varchar(100)')
 
 
class IntegerField(Field):
    def __init__(self, name):
        super(IntegerField, self).__init__(name, 'bigint')
 
 
class ModelMetaclass(type):
 
    def __new__(cls, name, bases, attrs):
        if name == "Model":
            return type.__new__(cls, name, bases, attrs)
        mappings = dict()
        print("Found class: %s" % name)
        for k, v in attrs.items():
            if isinstance(v, Field):
                print("Found mapping: %s ==> %s" % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs["__table__"] = name  # 表名和類(lèi)名一致
        attrs["__mappings__"] = mappings  # 保存屬性和列的映射關(guān)系
        return type.__new__(cls, name, bases, attrs)
 
 
class Model(metaclass=ModelMetaclass):
 
    def __init__(self, **kwargs):
        _setattr = setattr
        if kwargs:
            for k, v in kwargs.items():
                _setattr(self, k, v)
        super(Model, self).__init__()
 
    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(k)
            params.append("?")
            args.append(getattr(self, k, None))
        sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ",".join(params))
        print('插入語(yǔ)句: %s' % sql)
        print('參數(shù): %s' % str(args))
 
    def update(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            if getattr(self, k, None):
                fields.append(k+"=?")
                args.append(getattr(self, k, None))
        sql = "update %s set %s" % (self.__table__, ','.join(fields))
        print("更新語(yǔ)句: %s " % sql)
        print("參數(shù): %s" % args)
 
    def filter(self, *args):
        pass
 
    def delete(self):
        pass
 
 
class UserInfo(Model):
    """
        定義類(lèi)的屬性到列的映射
    """
    uid = IntegerField('uid')
    name = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
 
class Person(Model):
    """
    定義類(lèi)的屬性到列的映射
    """
    pid = IntegerField('id')
    names = StringField('username')
    email = StringField('email')
    password = StringField('password')
 
p = Person(pid=10086, names='曉明', email='10086@163.com', password='123456')
p.save()
u2 = UserInfo(password='123456')
u2.update()

到此這篇關(guān)于Python元類(lèi)編程實(shí)現(xiàn)一個(gè)簡(jiǎn)單的ORM的文章就介紹到這了,更多相關(guān)Python元類(lèi)編程實(shí)現(xiàn)ORM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python雙向隊(duì)列deque的使用

    python雙向隊(duì)列deque的使用

    本文主要介紹了python雙向隊(duì)列deque的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • python進(jìn)階_淺談面向?qū)ο筮M(jìn)階

    python進(jìn)階_淺談面向?qū)ο筮M(jìn)階

    下面小編就為大家?guī)?lái)一篇python進(jìn)階_淺談面向?qū)ο筮M(jìn)階。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • python讀取指定字節(jié)長(zhǎng)度的文本方法

    python讀取指定字節(jié)長(zhǎng)度的文本方法

    今天小編就為大家分享一篇python讀取指定字節(jié)長(zhǎng)度的文本方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • 加速Python代碼執(zhí)行利器使用實(shí)例探究

    加速Python代碼執(zhí)行利器使用實(shí)例探究

    這篇文章主要為大家介紹了加速Python代碼執(zhí)行的利器使用實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程

    window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程

    這篇文章主要介紹了window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Django logging配置及使用詳解

    Django logging配置及使用詳解

    這篇文章主要介紹了Django logging配置及使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • Python中關(guān)于浮點(diǎn)數(shù)的冷知識(shí)

    Python中關(guān)于浮點(diǎn)數(shù)的冷知識(shí)

    這篇文章主要給大家介紹了Python中關(guān)于浮點(diǎn)數(shù)的冷知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Python字符串的創(chuàng)建和駐留機(jī)制詳解

    Python字符串的創(chuàng)建和駐留機(jī)制詳解

    字符串駐留是一種在內(nèi)存中僅保存一份相同且不可變字符串的方法,本文重點(diǎn)給大家介紹Python字符串的創(chuàng)建和駐留機(jī)制,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • Python在字典中查找元素的3種方式

    Python在字典中查找元素的3種方式

    這篇文章主要介紹了Python在字典中查找元素的3種方式,字典是另一種可變?nèi)萜髂P?且可存儲(chǔ)任意類(lèi)型對(duì)象,需要的朋友可以參考下
    2023-04-04
  • Pytorch高階OP操作where,gather原理

    Pytorch高階OP操作where,gather原理

    這篇文章主要介紹了Pytorch高階OP操作where,gather原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04

最新評(píng)論