type() 內(nèi)置元類
# print(type('Hello'))
class Add():
pass
# print(type(Add)) # Add 類
# print(type(Add())) # Add()類的實(shí)例
# add = Add()
# print(type(add)) # add 實(shí)例化對象
# 利用 type() 函數(shù)動態(tài)創(chuàng)建一個類 ('func_name', (要繼承的父類), {類的屬性、類的實(shí)例屬性、類的方法})
# 注意!!! (要繼承的父類) 是一個元組[ 例子:(Add,) ]
print(type('Func', (), {}))
Func1 = type('Func1', (), {'className': 'Func'}) #使用元類 type() 創(chuàng)建出一個對象,這個對象稱為“類”
func1 = Func1() #使用“類”來創(chuàng)建出實(shí)例對象
print(func1.className)
自定義元類
實(shí)現(xiàn) ORM(對象關(guān)系映射) 對數(shù)據(jù)庫的 '增、刪、改、查'
1. 使用描述器定義字段屬性
# 定義字段屬性的基類Field,它的用處主要用于識別類屬性中屬于字段的那些屬性
class Field(object):
pass
# 整型字段屬性
class IntField(Field):
def __init__(self, db_column=""):
self._value = None # 表的數(shù)據(jù)
self.db_column = db_column
def __set__(self, instance, value):
if not isinstance(value, int):
raise ValueError("input should be a Integer")
self._value = value
def __get__(self, instance, owner):
return self._value
# 字符型字段屬性
class CharField(Field):
def __init__(self, db_column=""):
self._value = None
self.db_column = db_column
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
if not isinstance(value, str):
raise ValueError("input should be a String")
self._value = value
2. 定義元類
class MetaModel(type):
def __new__(cls, name, bases, attrs, **kwargs):
fields = {}
for key, val in attrs.items():
# 把a(bǔ)ttrs中與數(shù)據(jù)庫表字段有關(guān)的列提取出來
if isinstance(val, Field):
fields[key] = val # value 直接走描述器__get__()
_meta = {}
db_table = name.lower() # 數(shù)據(jù)表名稱默認(rèn)取小寫類名稱
_meta['db_table'] = db_table
attrs['_meta'] = _meta
attrs['_fields'] = fields
# 以上過程相當(dāng)于對類進(jìn)行了修改
return super(MetaModel, cls).__new__(cls, name, bases, attrs, **kwargs)
3. 定義模型基類
class Model(metaclass=MetaModel):
def __init__(self, *args, **kwargs):
for key, val in kwargs.items():
setattr(self, key, val)
return super(Model, self).__init__()
def save(self):
fields = []
values = []
for key, val in self._fields.items():
db_column = val.db_column
if db_column is None:
db_column = key.lower()
fields.append(db_column)
value = getattr(self, key) # 字段的值
values.append(str(value))
sql = "insert {name} ({field}) values ({value})".format(name=self._meta['db_table'],field=','.join(fields),value=','.join(values))
return sql
def select(self):
fields = []
where = []
for key, val in self._fields.items():
db_column = val.db_column
if db_column is None:
db_column = key.lower()
fields.append(db_column)
v = getattr(self, key, None)
if v is not None:
where.append([key, str(v)]) # [key, str(v)] 等價(jià)于 字典的鍵值對
# ['='.join(x) for x in where] => name=sean
sql = 'select {fields} from {name} where {where}'.format(name=self._meta['db_table'], fields=','.join(fields),where=' and '.join(['='.join(x) for x in where]),)
return sql