python 64式: 第11式、元類
阿新 • • 發佈:2018-11-08
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' 關鍵: 1 元類 含義:建立類的東西,用來建立這些類,是類的類 作用:1) 修改類,返回修改後的類 2) 物件關係對映,將定義的簡單類轉變成對資料庫的操作 目的: 當建立類時能夠自動改變類,希望可以建立符合當前上下文的類 類的型別是type,type可以動態建立類, 可以接收類的描述符作為引數,然後返回一個類 class ListMetaClass(type): # __new__(當前準備建立的類的物件,類的名字,類繼承的父類集合,類的方法集合) def __new__(cls, name, bases, attrs): attrs['add'] = lambda self, value: self.append(value) return type.__new__(cls, name, bases, attrs) class MyList(list): # 指示使用元類L來定義類的建立 __metaclass__ = ListMetaClass 2 type可以接收一個字典為類定義屬性 type(): 含義:是內建函式,可以動態建立類,接收類名作為引數,返回類 本質:是建立所有類的元類。 用法: type(類名,父類的元組【針對繼承的情況,可以為空】,包含屬性或方法的字典) def fn(self, name=''): return name Student = type('Student', (object,), {'getName': fn, 'age': 25}) print Student.age student = Student() name = student.getName('chen') 總結: 元類本質上是類的類,即類是元類的例項。由於元類可以定製化類的特性,會被用於 物件關係對映,新增自定義類方法等。效果等同於type(name, base, attrs)建立的類。 參考: [1] http://blog.jobbole.com/21351/ [2] https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386820064557c69858840b4c48d2b8411bc2ea9099ba000 [3] http://python.jobbole.com/88795/ ''' 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): # __new__(當前準備建立的類的物件,類的名字,類繼承的父類集合,類的方法集合) def __new__(cls, name, bases, attrs): if 'Model' == name: return type.__new__(cls, name, bases, attrs) mappings = dict() for k, v in attrs.iteritems(): if isinstance(v, Field): mappings[k] = v # 將原來屬性字典中已經有Field的鍵值對刪除,否則執行錯誤 for k in mappings.iterkeys(): attrs.pop(k) # 假設表名和類名一致 attrs['__table__'] = name # 儲存屬性和值的對映關係 attrs['__mappings__'] = mappings return type.__new__(cls, name, bases, attrs) class Model(dict): __metaclass__ = ModelMetaclass def __init__(self, **kw): super(Model, self).__init__(**kw) def __getattr__(self, key): return self[key] def save(self): fields = [] values = [] # 遍歷屬性和值的對映 for k, v in self.__mappings__.iteritems(): fields.append(v.name) values.append(str(getattr(self, k, None))) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(values)) print "sql: %s" % (sql) class User(Model): # 定義類的屬性到列的對映 id = IntegerField('id') name = StringField('username') def userMetaClassORM(): u = User(id=12345, name='Chen') # 儲存到資料庫,由metaclass完成 u.save() def process(): userMetaClassORM() if __name__ == "__main__": process()