日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python中通过元类(TYPE)简单实现对象关系映射(ORM)

發布時間:2023/12/10 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python中通过元类(TYPE)简单实现对象关系映射(ORM) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ORM是創建一個實例對象,用創建他的類名當做數據表名,用創建他的類屬性對應數據表的字段,不需要在自己寫復雜的sql語句,而是通過對實例對象的操作時,能讓代碼自動幫我們整理為對應的sql語句。

class User(父類):uid = ("uid", "int unsigned")name = ("username", "varchar(20)")password = ("password", "varchar(20)")...省略...

?

數據庫
uid username password
???
???

?

類似下圖創建一個實例對象,把數據庫的數據以參數入

u = User(nid=12345, name="laowang",password="123321")

通過調用某個方法,ORM自動幫我們整理為下面代碼并執行:

insert into (uid,name,password) value (12345,"laowang","123321")

從而大大簡化我們的工作,減少出錯率!下面是完整代碼(通過metaclass可以指定我們需要繼承的元類):

class Mode_type(type):def __new__(cls, name, bases, attrs)mappings = dict()for k, v in attrs.items():if isinstanse(v, tuple):mappings[k] = v# 找到新字典接收完attrs的數據后,刪掉attrs里的數據for k in mappings.keys[]:attrs.pop(k)# 將之前新字典保存的數據表的信息保存在attrs中attrs["__mappings__"] = mappings# name指向新創建的實例對象名,相當于保存數據表的名稱attrs["__table__"] = name return type.__new__(cls, name, bases, attrs)class User(mateclass = Mode_type):uid = ("uid", "int unsigned")name = ("username", "varchar(20)")password = ("password", "varchar(20)")# 指定元類后,以上的類屬性就不在類中,而是在__mapping__指定的字典中倉儲# 類似于# __mapping__ = {# uid :("uid", "int unsigned")# name: ("username", "varchar(20)")# password :("password", "varchar(20)")# }# __table__ = "User"def __init__(self, **kwargs):# 取出字典里面的值for name, value in kwargs.items():setattr(self, name, value)# 這里不能用self.name = value ,這樣只會讓實例對象擁有name這個屬性,而不是name形參背后真正替換的屬性,所以用setattrdef save()# 數據表表頭字段fields = []# 數據表字段對應的數據args = []for k, v in self.__mappings__.items():field.append(v[0])args.append(getattr(self, k, None))args_temp = list()# 區分參數的類型,防止寫入數據表后報錯for temp in args:if isinstence(temp, int):args_temp.append(str(temp)) # 類似temp = “123456”elif isinstence(temp, str):args_temp.append("""%s""" % temp) # 類似temp = """'123321'"""sql = "insert into %s (%s) value (%s)" % (self.__table__, ",".join(fields), ",".join(args_temp))# 下面就可以執行mysql的操作,只是說ORM,所以我只打印了這句話 print(sql)u = User(uid = 123456, name="laowang", password = "123321") u.save()

需要注意的點:

  • Metaclass的父類:Metaclass是類的模板,所以必須從`type`類型繼承:
  • 選擇__new__函數作為實現"修改類"的函數
    • 函數__new__(cls, name,bases,attrs)中,"cls"類似于類中其他函數的self參數,例如__init__(self),只不過self代表創建的對象,而cls代表類本身(__init__作為實例初始化的函數,需要把實例本身作為參數傳進去,這樣我們才能保證被修改的是實例;同理,__new__函數需要把類本身作為參數傳進去,才能保證被初始化的是當前類);?name代表類的名稱;bases代表當前類的父類集合;attrs代表當前類的屬性,是狹義上屬性和方法的集合,可以用字典dict的方式傳入
    • 其實我們看下用type創建一個類就很好理解這些參數了(): u = type('User', (object,),{uid:("uid", "int unsigned"),name :("username", "varchar(20)"),password:("password", "varchar(20)"})
    • 對__new__的定義def?__new__(cls, name,bases,attrs),實際上,“new”方法在Python中是真正的構造方法(創建并返回實例),通過這個方法可以產生一個”cls”對應的實例對象所以說”new”方法一定要有返回,要把創建的實例對象返回回去。在此,我們把對類的修改放到__new__方法中,然后返回修改過后的實例對象。另外,很簡單的道理,選擇type.__new__函數作為return的值,是因為我們的Mode_type繼承自type,因此應該返回type的__new__函數創建的對象。

轉載于:https://www.cnblogs.com/lzb888/p/11145901.html

總結

以上是生活随笔為你收集整理的python中通过元类(TYPE)简单实现对象关系映射(ORM)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。