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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python——type()、metaclass元类和精简ORM框架

發(fā)布時(shí)間:2025/3/21 python 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python——type()、metaclass元类和精简ORM框架 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、type()函數(shù)

#type()函數(shù)既可以返回一個(gè)對(duì)象的類型,又可以創(chuàng)建出新的類型, # 比如,我們可以通過(guò)type()函數(shù)創(chuàng)建出Hello類,而無(wú)需通過(guò)class Hello(object)...的定義:def fn(self,name='world'): #先定義函數(shù)print('Hello, %s.'%name) #開(kāi)始用type() hello = type('Hello',(object,),dict(hello=fn)) # 創(chuàng)建Hello class #要?jiǎng)?chuàng)建一個(gè)class對(duì)象,type()函數(shù)依次傳入3個(gè)參數(shù): #class的名稱; #繼承的父類集合,注意Python支持多重繼承,如果只有一個(gè)父類,別忘了tuple的單元素寫(xiě)法; #class的方法名稱與函數(shù)綁定,這里我們把函數(shù)fn綁定到方法名hello上。

  

if __name__ == '__main__':h = hello()h.hello()print(type(hello))print(type(h))

?

Hello, world. <class 'type'> <class '__main__.Hello'>

?

2、metaclass元類

#metaclass 元類 metaclass允許你創(chuàng)建類或者修改類 class Listmetaclass(type): def __new__(cls, name,bases,attrs): attrs['add'] = lambda self,value:self.append(value) #增加了add()方法 return type.__new__(cls,name,bases,attrs) class MyList(list,metaclass=Listmetaclass): pass #__new__()方法接收到的參數(shù)依次是: #1、當(dāng)前準(zhǔn)備創(chuàng)建的類的對(duì)象; #2、類的名字; #3、類繼承的父類集合; #4、類的方法集合。 #元類一般情況不常用,但總會(huì)遇到需要通過(guò)metaclass修改類定義的。ORM就是一個(gè)典型的例子。 #ORM全稱“Object Relational Mapping”,即對(duì)象-關(guān)系映射,就是把關(guān)系數(shù)據(jù)庫(kù)的一行映射為一個(gè)對(duì)象, # 也就是一個(gè)類對(duì)應(yīng)一個(gè)表,這樣,寫(xiě)代碼更簡(jiǎn)單,不用直接操作SQL語(yǔ)句。 #要編寫(xiě)一個(gè)ORM框架,所有的類都只能動(dòng)態(tài)定義,因?yàn)橹挥惺褂谜卟拍芨鶕?jù)表的結(jié)構(gòu)定義出對(duì)應(yīng)的類來(lái)。 ?

  

if __name__ == '__main__': L = MyList() L.add(2) #增加了add()方法 L.add(3) print(L)

[2, 3]

3、精簡(jiǎn)ORM框架

#開(kāi)始編寫(xiě)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') #下一步,就是編寫(xiě)最復(fù)雜的ModelMetaclass了: class ModelMetaclass(type): def __new__(cls, name,bases,attrs): if name == 'Model': #排除掉對(duì)Model類的修改; return type.__new__(cls,name,bases,attrs) print('Found Model: %s'%name) mappings = dict() for k,v in attrs.items(): #查找定義的類的所有屬性, if isinstance(v,Field): #如果找到一個(gè)Field屬性, print('Found mapping: %s ==> %s' % (k, v)) mappings[k] = v #就把它保存到一個(gè)__mappings__的dict中 for k in mappings.keys(): attrs.pop(k) #同時(shí)從類屬性中刪除該Field屬性,否則,容易造成運(yùn)行時(shí)錯(cuò)誤(實(shí)例的屬性會(huì)遮蓋類的同名屬性); attrs['__mappings__'] = mappings # 保存屬性和列的映射關(guān)系 attrs['__table__'] = name # 假設(shè)表名和類名一致 把表名保存到__table__中 return type.__new__(cls,name,bases,attrs) #基類Model class Model(dict,metaclass=ModelMetaclass): def __init__(self,**kw): super(Model,self).__init__(**kw) def __getattr__(self, item): #沒(méi)有找到的屬性,就在這里找 try: return self[item] except KeyError: raise AttributeError(r"'Model' object has no attrs :'%s'"%item) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k,v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self,k,None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args)) #子類User # 定義類的屬性到列的映射: class User(Model): id = IntegerField('id') name = StringField('username') email = StringField('email') password = StringField('password') age = IntegerField('age')

#開(kāi)始編寫(xiě)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')
#下一步,就是編寫(xiě)最復(fù)雜的ModelMetaclass了:
class ModelMetaclass(type):
??? def __new__(cls, name,bases,attrs):
??????? if name == 'Model':? #排除掉對(duì)Model類的修改;
??????????? return type.__new__(cls,name,bases,attrs)
??????? print('Found Model: %s'%name)
??????? mappings = dict()
??????? for k,v in attrs.items(): #查找定義的類的所有屬性,
??????????? if isinstance(v,Field): #如果找到一個(gè)Field屬性,
??????????????? print('Found mapping: %s ==> %s' % (k, v))
??????????????? mappings[k] = v? #就把它保存到一個(gè)__mappings__的dict中
??????? for k in mappings.keys():
??????????? attrs.pop(k)? #同時(shí)從類屬性中刪除該Field屬性,否則,容易造成運(yùn)行時(shí)錯(cuò)誤(實(shí)例的屬性會(huì)遮蓋類的同名屬性);
??????? attrs['__mappings__'] = mappings # 保存屬性和列的映射關(guān)系
??????? attrs['__table__'] = name? # 假設(shè)表名和類名一致? 把表名保存到__table__中
??????? return type.__new__(cls,name,bases,attrs)

#基類Model
class Model(dict,metaclass=ModelMetaclass):
??? def __init__(self,**kw):
??????? super(Model,self).__init__(**kw)
??? def __getattr__(self, item):? #沒(méi)有找到的屬性,就在這里找
??????? try:
??????????? return self[item]
??????? except KeyError:
??????????? raise AttributeError(r"'Model' object has no attrs :'%s'"%item)

??? def __setattr__(self, key, value):
??????? self[key] = value

??? def save(self):
??????? fields = []
??????? params = []
??????? args = []
??????? for k,v in self.__mappings__.items():
??????????? fields.append(v.name)
??????????? params.append('?')
??????????? args.append(getattr(self,k,None))
??????? sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
??????? print('SQL: %s' % sql)
??????? print('ARGS: %s' % str(args))

#子類User
# 定義類的屬性到列的映射:
class User(Model):
??? id = IntegerField('id')
??? name = StringField('username')
??? email = StringField('email')
??? password = StringField('password')
??? age = IntegerField('age')

 

當(dāng)用戶定義一個(gè)class User(Model)時(shí),Python解釋器首先在當(dāng)前類User的定義中查找metaclass,如果沒(méi)有找到,就繼續(xù)在父類Model中查找metaclass,找到了,就使用Model中定義的metaclass的ModelMetaclass來(lái)創(chuàng)建User類,也就是說(shuō),metaclass可以隱式地繼承到子類,但子類自己卻感覺(jué)不到。


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


  • 排除掉對(duì)Model類的修改;


  • 在當(dāng)前類(比如User)中查找定義的類的所有屬性,如果找到一個(gè)Field屬性,就把它保存到一個(gè)__mappings__的dict中,同時(shí)從類屬性中刪除該Field屬性,否則,容易造成運(yùn)行時(shí)錯(cuò)誤(實(shí)例的屬性會(huì)遮蓋類的同名屬性);


  • 把表名保存到__table__中,這里簡(jiǎn)化為表名默認(rèn)為類名。


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


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

    編寫(xiě)代碼試試: ? if __name__ == '__main__': u = User(id = 12345,name = 'john',email = '123456789@qq.com',password = '666666') u.age = 12 u.save()

    ?

    Found Model: User Found mapping: id ==> <IntegerField:id> Found mapping: name ==> <StringField:username> Found mapping: email ==> <StringField:email> Found mapping: password ==> <StringField:password> Found mapping: age ==> <IntegerField:age> SQL: insert into User (id,username,email,password,age) values (?,?,?,?,?) ARGS: [12345, 'john', '123456789@qq.com', '666666', 12]

     

    即User類中做好了到列的映射的類屬性,都能添加到sql語(yǔ)句中,而未做好了到列的映射的類屬性:如height,則會(huì)過(guò)濾掉,實(shí)現(xiàn)數(shù)據(jù)庫(kù)列的字段的高度可定制
    if __name__ == '__main__': u = User(id = 12345,name = 'john',email = '123456789@qq.com',password = '666666',height = 180) # u.age = 12 u.save()

    ?

    Found Model: User Found mapping: id ==> <IntegerField:id> Found mapping: name ==> <StringField:username> Found mapping: email ==> <StringField:email> Found mapping: password ==> <StringField:password> Found mapping: age ==> <IntegerField:age> SQL: insert into User (id,username,email,password,age) values (?,?,?,?,?) ARGS: [12345, 'john', '123456789@qq.com', '666666', None]

    ?


    即使在初始化的時(shí)候傳進(jìn)了height參數(shù),依然會(huì)被過(guò)濾掉,而定義好了到列的映射的類屬性age,即使沒(méi)有賦值,也會(huì)被默認(rèn)為None,并添加到數(shù)據(jù)庫(kù)中。 注:可以看到,save()方法已經(jīng)打印出了可執(zhí)行的SQL語(yǔ)句,以及參數(shù)列表,只需要真正連接到數(shù)據(jù)庫(kù),執(zhí)行該SQL語(yǔ)句,就可以完成真正的功能。下面入庫(kù)操作,還有剩下的刪改查操作可自行解決。

    轉(zhuǎn)載于:https://www.cnblogs.com/MY0213/p/9011739.html

    總結(jié)

    以上是生活随笔為你收集整理的python——type()、metaclass元类和精简ORM框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。