zoukankan      html  css  js  c++  java
  • Python元类的使用

    前言

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

    使用type()创建类

    def fn(self, name="word"):
    	print("hello, %s" % name)
    
    
    Hello = type('Hello', (object, ), dict(hello=fn))
    

    type()依次接收3个参数

    1. class名称
    2. 继承的父类的集合, 如果只有一个父类,注意tuple的单元素写法
    3. 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__()接收

    1. 当前准备创建的对象 cls
    2. 类名
    3. 类继承的父类集合
    4. 类的方法集合

    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 '<%s:%s>' % (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 0x00000000028094E0>, 
    		'name': <__main__.StringField object at 0x0000000002809518>, 
    		'email': <__main__.StringField object at 0x00000000028094A8>, 
    		'password': <__main__.StringField object at 0x0000000002809550>}
    		'''
    		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 ==> <IntegerField:id>
    Found mapping: name ==> <StringField:username>
    Found mapping: email ==> <StringField:email>
    Found mapping: password ==> <StringField:password>
    SQL: insert into User (id,username,email,password) values (?,?,?,?)
    ARGS: [12345, 'Michael', 'test@orm.org', 'my-pwd']
    

    引用

    https://www.liaoxuefeng.com/wiki/1016959663602400/1017592449371072

  • 相关阅读:
    Scala: 包对象
    云服务使用技巧
    leetcode上一些常见的链表问题
    数据挖掘的价值
    leetcode上的一些分治算法
    双指针的应用
    KNN算法
    线性回归
    leetcode上的一些单链表
    leetcode上的一些栈、队列问题
  • 原文地址:https://www.cnblogs.com/sayiqiu/p/10968234.html
Copyright © 2011-2022 走看看