看這個代碼之前先去看上篇文章,理解type的用法及元類的含義:
ORM可以代替pymysql,實現將python語義裝換為sql語句,簡單化
import pymysql
''' metaclass,直譯為元類,簡單的解釋就是: 當我們定義了類以后,就可以根據這個類創建出實例,所以:先定義類,然后創建實例。 但是如果我們想創建出類呢?那就必須根據metaclass創建出類,所以:先定義metaclass,然后創建類。 連接起來就是:先定義metaclass,就可以創建類,最后創建實例。 所以,metaclass允許你創建類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“實例”。 當我們傳入關鍵字參數metaclass時,魔術就生效了,它指示Python解釋器在創建Student時, 要通過ModelMetaClass.__new__()來創建,在此,我們可以修改類的定義,比如,加上新的方法,然后,返回修改后的定義。 '''
class Field(object):#定義一個字段類
def __init__(self,name,column_type):
self.name = name#字段名
self.column_type = column_type#字段類型
def __str__(self):
return "<%s:%s>"%(self.name,self.column_type)
class StringField(Field):#字符串類型字段,繼承Field
def __init__(self,name):
super(StringField,self).__init__(name,"varchar(100)")
# super(StringField, self).__init__(name,char(20))
class IntegerField(Field):#數字類型字段,繼承Field
def __init__(self,name):
super(IntegerField,self).__init__(name,"int")
class ModelMetaClass(type):#定義一個元類
def __new__(cls, name,bases,attrs):
''' :param name: 類的名稱 :param bases: 類的繼承 :param attrs: 類的屬性 :return: '''
if name == "Model":#如果傳入的name:類名為Model則不進行操作,直接返回type類的相關參數
return type.__new__(cls,name,bases,attrs)
# return super(ModelMetaClass, self).__new__(cls,name,bases,attrs)
print('Found model: %s' % name) # 打印當前實例的類名稱
mapping = dict() #空字典
for k,v in attrs.items(): #遍歷屬性
print('key:%s,value:%s' % (k, v))#打印遍歷attrs的key和value
if isinstance(v,Field): #判斷屬性是否Field的實例
mapping[k] = v #添加到mapping當中
# print(mapping)
for k in mapping.keys(): #返回所有鍵
attrs.pop(k) #mapping里存在的內容從屬性當中刪除
attrs["__mapping__"] = mapping #設定__mapping__屬性來保存字段
attrs["__table__"] = name #設定類名和表名一致(不區分大小寫)
# print(attrs)
return type.__new__(cls,name,bases,attrs)#返回給類實例,這里為Student
class Model(dict,metaclass = ModelMetaClass):#創建一個實例類,設置其元類
def __init__(self,**kwargs):
self.db = pymysql.connect(#鏈接數據庫
host = "localhost",
user = "root",
password = "123",
database = "test"
)
self.cursor = self.db.cursor()
super(Model,self).__init__(**kwargs)
def __getattr__(self, key):
return self[key]#返回對象的屬性值
# print(self[key])
def __setattr__(self, key, value):
self[key] = value#設置對象的屬性及其對應的值
def save(self):
fields = [] #空列表用來存儲字段
args = [] #空列表用來存儲字段的值
for k,v in self.__mapping__.items():
fields.append(v.name)#此時,v為field子類的實例,因此可以取出類屬性name,作為字段名
# print(getattr(self, k, None))
args.append(getattr(self,k,None))#此時調用了self,則將傳入的參數調用,此時再取變量的值,則為傳入的實參
sql = "insert into %s(%s) values (%s)"%(
self.__table__,
",".join(fields),
",".join([repr(str(i)) for i in args]
)) #sql拼接
self.cursor.execute(sql)
print(sql)
def __del__(self):
''' 回收內存 '''
self.db.commit()
self.cursor.close()
self.db.close()
class Student(Model):#model實例類的子類
name = StringField("name")
# print(name)
room_id = IntegerField("room_id")
# print(room_id)
u = Student(name = "張3",room_id = 6)#實質是創建了一個字典的對象
u.save()#調用父類的save方法