Python的类
在Python中类也是一个对象,可以使用type()
内置函数动态创建类
MyClass = type('MyClass', (object,), {})
my_instance = MyClass()
print(MyClass)
print(my_instance)
⬇️
<class '__main__.MyClass'>
<__main__.MyClass object at 0x10ba00fa0>
函数type()
实际是一个元类,通过参数创建一个类对象。
Python的元类
Python中的元类和类的关系和java一样,实例对象是类对象的实例,而类对象是元类的实例,简单点来说就是元类是用来创建类的,而类是用来创建实例的
class MyMetaclass(type):
pass
class MyClass(object, metaclass=MyMetaclass):
pass
my_instance = MyClass()
实例 => 类 => 元类
上面我们通过type()
这个元类创建了MyClass
这个类对象,下面自定义一个元类并为类对象添加一些方法和属性⬇️
class ListMetaclass(type):
def __new__(mcs, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
attrs['name'] = 'Bob Dylan'
print(mcs, name, bases, attrs.items())
return type.__new__(mcs, name, bases, attrs)
class MyList(list, metaclass=ListMetaclass):
pass
这样就为MyList
这个类添加了add
方法和name
属性
l = MyList()
l.add(10)
l.add(20)
print(l)
⬇️
[10, 20]
Bob Dylan
MyList
类的生成大约有几个步骤:
1.
MyList
有metaclass
属性吗?如果有,Python会在内存中通过__metaclass__
创建一个名字为MyList
的类对象
2.如果没有,则继续查找父类,并重复1的步骤
3.如果父类中也没有,会在模块层次中查找,并重复1的步骤
4.如果还是查找不到,Python
会用内置的type()
函数创建类对象
使用元类实现ORM
ORM是什么?
1.定义Field类,负责保存数据库表的字段名和字段类型:
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, '(varchar100)')
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint')
2.定义元类
class ModelMetaclass(type):
def __new__(mcs, name, bases, attrs):
if name == "Model":
return type.__new__(mcs, name, bases, attrs)
mapping = dict()
for k, v in attrs.items():
if isinstance(v, Field):
mapping[k] = v
for k in mapping.keys():
attrs.pop(k) # 将类属性移除,使定义的类字段不污染User类属性,只在实例中可以访问这些key
attrs['__mapping__'] = mapping # 保存映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(mcs, name, bases, attrs)
3.定义Model类
class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kw):
super(Model, self).__init__(**kw)
def __getattr__(self, item): # 获取属性
try:
return self[item]
except KeyError:
raise AttributeError('Model object has no attribute %s ' % item)
def __setattr__(self, key, value): # 设置属性
self[key] = value
def save(self):
fields = []
params = []
args = []
for k, v in self.__mapping__.items(): # 查找映射关系
fields.append(v.name)
params.append('?')
args.append(self[k])
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
4.使用
class User(Model):
id = IntegerField('id')
name = StringField('username')
password = StringField('password')
age = IntegerField('age')
user = User(id=10086, name='ty', password='123456', age=18)
user.save()
输出⬇️
SQL: insert into User (id,username,password,age) values (?,?,?,?)
ARGS: [10086, 'ty', '123456', 18]
映射关系如下⬇️:
通过
Field
类的name
与dict
的key
建立映射关系
网友评论