python中通过元类(TYPE)简单实现对象关系映射(ORM)
生活随笔
收集整理的這篇文章主要介紹了
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)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java反编译器Java Decompi
- 下一篇: python matplotlib绘图大