python高级编程-关于python元类的最全资料整理

python的基础知识

  1. python 中一切都是对象。(字符串 整数 元组 字典等是对象,函数、类也是对象
  2. 类是对象,那么是谁的对象?即类对象(类)是谁的对象?
  3. type函数的作用:1.调用时给参数(对象),打印出对象的类;2.手动生成类,跟class关键字作用类似
  4. python中的两个链:1.类的继承链;2.类(也是对象)的实例化链

类定义的两种方式(等价)

  1. 自动定义(class 关键字)
>>> class Animal(object):
		'''Animal类,继承顶级类object'''
		def __init__(self, name):
			self.name = name
		def eat(self):
			pass
		def go_to_vet(self):
			pass
	
		
>>> class Cat(Animal):
	'''Cat类,继承Animal类'''
		def meow(self):
			pass
		def purr(self):
			pass
  1. 手动定义(type函数)

type函数的使用:

  1. 第一个参数是一个字符串’Animal’,发送该字符串将其作为类名称,但也将type调用的结果赋给变量Animal。class关键字可以为你完成上面的操作。由于这里直接调用type,因此必须手动将结果赋给变量,就像在为其他类的新实例所做的一样。
  2. 第二个参数是只包含一个成员的元组:(object,)。这表示Animal类继承自object,与之前的类一样。需要在元组尾部加逗号,让Python解释器将其作为元组。括号在Python中有其他用处,因此对于只包含一个元素的元组需要在结尾处加逗号。
  3. 第三个参数是一个字典,定义了类的属性,等价于class代码块内缩进的代码部分。
>>> def init(self, name):
		self.name = name

	
>>> def eat(self):
		pass

>>> def go_to_vet(self):
		pass

>>> Animal = type('Animal', (object,), {
		'__doc__': 'A class representing an arbitrary animal.', 
		'__init__': init,
		 'eat': eat,
		  'go_to_vet': go_to_vet,
	})
	
>>> def meow(self):
	pass
		
>>> def purr(self):
	pass
>>> Cat = type('Cat', (Animal,), {
		'meow': meow,
		 'purr': purr,
		 })	

元类

类是对象,叫类对象。类对象的类叫元类。

元类的定义

  1. class定义(推荐方法)
>>> class Meta(type):
		'''A custom metaclass that adds actual functionality.'''
		def __new__(cls, name, bases, attrs):
			return super(Meta, cls).__new__(cls, name, bases, attrs)
  1. type定义(或者用type的子类定义)
>>> C = Meta('C', (object,), {})

元类的继承原则

一个类只能有一个元类。冲突时,有以下规则:

  1. 如果一个类的多个子类有不同的元类,Python的解释器会通过检查元类的起源来解决该冲突,如果其元类关系为直接继承,则最终使用子类。
>>> class Z(C, N):
		pass

>>> type(Z)
<class '__main__.Meta'>
  1. 如果两个元类中的一个并不是另一个的直接子类,Python解释器并不知道该如何解决,因此会拒绝尝试执行(报错)
>>> class OtherMeta(type):
		def __new__(cls, name, bases, attrs):
			return super(OtherMeta, cls).__new__(cls, name, bases, attrs)

	
>>> OtherC = OtherMeta('OtherC', (object,), {})
>>> class Invalid(C, OtherC):
		pass

Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    class Invalid(C, OtherC):
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

元类的使用语法

  1. Python3
>>> class C(metaclass = Meta):
		pass
  1. Python2
>>> class C(object,metaclass = Meta):
		pass
  1. 兼容Python2和Python3
import six
class C(six.with_metaclass(Meta)):
	pass
import six
@six.add_metaclass(Meta)
class C(object):
	pass

元类的用途

元类的主要用途是手动创建类,即在类产生前做一些工作。最常见的应用场景是ORM模型。ORM中,表是类,字段是属性,记录是对象。那么,不同表的字段不同,即不同类的属性是不同的;但是每个表都有CURD(增删改查)操作。思路来了,那就是在类产生的过程中做手脚,不同类产生不同的属性,所以手动创建类就派上用场了。代码如下:

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(100)')

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':
            return type.__new__(cls, name, bases, attrs)
        print('Found model: %s' % name)
        mappings = dict()
        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)
        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)
            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()

整理资料出处

  1. https://blog.youkuaiyun.com/weixin_38853600/article/details/82979026
  2. https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值