今天讲一下元类的概念,使用方法,以及它的一个用途–ORM
讲元类之前,首先要明确对象的概念,以及两个方法,globals()和__builtins__
globals():可以查看python中有地址的可执行对象
__builtins__
- 为什么不用导包或者模块局可以使用print(),input()等函数?因为这些方法是解释器内置的内建函数
- 可以使用__builtins__.dict来以字典的形式来查看所有的内建函数
- 对象
- 对象是指被分配了地址的东西,对象用一个名字来引用这个被分配的地址,一切的对象的传递,都是引用的传递
- 在Python中,变量是对象,函数是对象,类是对象,一切皆对象
元类
- 元类是创建类对象的东西,它是一切类对象的最终父类,它本身也是一个类对象
- 用type来表示元类
创建元类的格式
<类名> = type("<类名>",(<父类名>,...),{“<属性>”:<值>,...“<方法名>”:<方法名>}
创建一个有参数的类
创建一个有方法的类
- 元类可以用来更改类
- 在Python2 和python3中更改类的方式是不一样的
- 在Python2 中,在类属性位置使用__metaclass__== <元类名>来进行对类的修改操作
- 在Python3中,在定义中,添加父类,metaclass=<元类名>进行更改类的操作
ORM
- orm 是用类的形式,创建数据库表对象,用调用方法的形式对数据表进行增删改查等操作,程序员不需要关心具体的数据库操作逻辑,甚至不需要会写sql语句
- 简而言之,就是在Python中,更直观,舒服的书写数据库操作的代码,让其他合作者更舒服的调用
orm生成步骤
1.直接操作数据库表
- 简单直接
问题
- 重复代码多
- 当查询内容变化时,需要重新写,sql语句,比价麻烦
2.使用字典去生成SQL语句的格式化内容
- 解决了直接操作数据库的问题2
问题
- 仍然有重复代码
- 写法上不够明确
3.把数据库的操作封装成一个类,使用对象进行操作
- 直观,好理解
问题
- 还可以再改点什么?
4.创建一个元类的父类
- 引出强大的元类
问题
- 还可以再做点什么?
5.使用一个类去封闭我们的字段
- 完美呈现?
完整代码
from pymysql import *
class Field(object):
def __init__(self,data):
self.data = data
class MyMetaClass(type):
def __new__(cls, class_name,supers_name,attrs):
print(attrs)
create_dict = dict() # 创建我们字段的字典
for key,value in attrs.items():
if isinstance(value,Field): # 我们要的是元组数据
create_dict[key] = value.data
attrs['create_dict'] = create_dict # 自动生成一个属性的字典
attrs['table_name'] = class_name.lower()
# 删除以前自己写的字段
for key in create_dict.keys():
print(key)
attrs.pop(key)
return type.__new__(cls,class_name,supers_name,attrs)
class Table(object,metaclass=MyMetaClass):
def create(self):
# 创建Connection连接
conn = connect(host='localhost',port=3306,database='stock_db',user='root',password='mysql',charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
fields = list()
for key,value in self.create_dict.items():
fields.append("%s %s"%(key,value))
print(self.create_dict)
# 创建表
create_sql = """ CREATE TABLE IF NOT EXISTS %s(%s);"""%(self.table_name,",".join(fields),)
print(create_sql)
cs1.execute(create_sql)
# 提交
conn.commit()
# 关闭
cs1.close()
conn.close()
def insert(self,**kwargs):
print(kwargs)
# 创建Connection连接
conn = connect(host='localhost', port=3306, database='stock_db', user='root', password='mysql', charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
keys = list()
values = list()
for key,value in kwargs.items():
keys.append(key)
# 如果是Int转成字符串
if isinstance(value , int):
# 说明 int
values.append(str(value))
else:
values.append(""" "%s" """%value)
insert_sql = """ insert into %s (%s) values (%s);"""%(self.table_name,",".join(keys),",".join(values))
print(insert_sql)
cs1.execute(insert_sql)
# 提交
conn.commit()
# 关闭
cs1.close()
conn.close()
class LowUser(Table):
name = Field("varchar(20)")
password = Field("varchar(20)")
class Login(Table):
name = Field("varchar(20)")
dress = ("varchar(20)",)
def main():
lowUser = LowUser()
lowUser.create()
lowUser.insert(name = "old样",password = "654321")
login = Login()
login.create()
login.insert(name = "898989")
print(Login.name)
if __name__ == '__main__':
main()