python元类使用场景_Python元类的使用

前言

本文以廖雪峰网页的元类示例为基础,进行一些补充注解,原文参见文末链接。

使用type()创建类

def fn(self, name="word"):

print("hello, %s" % name)

Hello = type('Hello', (object, ), dict(hello=fn))

type()依次接收3个参数

class名称

继承的父类的集合, 如果只有一个父类,注意tuple的单元素写法

class的方法名称与函数绑定

MetaClass

定义类的时候要显式指明metaclass=xxx

这样会指示python解释器在创建类时,调用xxxMetaclass.__new__()来创建

class ListMetaclass(type):

def __new__(cls, name, bases, attrs):

attrs['add'] = lambda self, value: self.append(value)

return type.__new__(cls, name, bases, attrs)

__new__()接收

当前准备创建的类对象 cls

类名

类继承的父类集合

类的方法集合

ORM(Object Relational Mapping)

class Field(object):

def __init__(self, name, column_type):

self.name = name

self.column_type = column_type

def __str__(self):

return '' % (self.__class__.__name__, self.name)

class StringField(Field):

def __init__(self, name):

super(StringField, self).__init__(name, 'varchar(1000)')

class IntegerField(Field):

def __init__(self, name):

super(IntegerField, self).__init__(name, 'bigint')

class ModelMetaclass(type):

def __new__(cls, name, bases, attrs):

if name == 'Model':

# 先在User中找Meta, 没有找到

# 然后到父类Model里找, 发现可以找到

# 就会使用Model的MetaClass先初始化User()

# 因为在本例中MetaClass不打算修改Model, 所以要在代码中排除掉Model

return type.__new__(cls, name, bases, attrs)

print('Found model: %s' % name)

mappings = dict()

'''

attr = {

'__module__': '__main__',

'__qualname__': 'User',

'id': <__main__.integerfieldobject at>,

'name': <__main__.stringfield object at>,

'email': <__main__.stringfield object at>,

'password': <__main__.stringfield object at>}

'''

for k, v in attrs.items():

if isinstance(v, Field): # 去掉多余的键值

print("Found mapping: %s ==> %s" % (k, v))

mappings[k] = v

for k in mappings.keys():

attrs.pop(k) # 此时只剩__module__ 和 __qualname__

attrs['__mappings__'] = mappings

attrs['__table__'] = name # 类名

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):

try:

return self[key]

except KeyError:

raise AttributeError(r"'Model' object has no attribute '%s'" % key)

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) # id, username, email, password

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))

class User(Model):

id = IntegerField('id') #

name = StringField('username')

email = StringField('email')

password = StringField('password')

u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')

u.save()

# out:

Found model: User

Found mapping: id ==>

Found mapping: name ==>

Found mapping: email ==>

Found mapping: password ==>

SQL: insert into User (id,username,email,password) values (?,?,?,?)

ARGS: [12345, 'Michael', 'test@orm.org', 'my-pwd']

引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值