Python3 元类(metaclass)

Python3 元类(metaclass)

1. 类也是对象

  1. 赋值给一个变量
  2. 可以作为参数进行传递
  3. 可以动态增加它的属性
  4. 可以拷贝
class ObjectClass(object):
    pass

valObj = ObjectClass # 可以赋值

obj1 = ObjectClass()
obj2 = valObj()
print(obj1, obj2)

def testfunc(obj): # 可以作为参数传递
    return obj()

obj3 = testfunc(ObjectClass)
print(obj3)

print(hasattr(ObjectClass, 'new_attr'))
ObjectClass.new_attr = 'Megvii'  # 可以动态的增加属性
print(hasattr(ObjectClass, 'new_attr'))

import copy
ObjcetC_C = copy.copy(ObjectClass)  # 可以拷贝
print(ObjcetC_C)
print(ObjcetC_C is ObjectClass)

<__main__.ObjectClass object at 0x1023a45f8> <__main__.ObjectClass object at 0x1023a4518>
<__main__.ObjectClass object at 0x102371f98>
False
True
<class '__main__.ObjectClass'>
True

那么就有一个问题了:既然 类本身是一个对象,那这个对象是谁创建的????

obj4 = ObjectClass()
print(obj4)

大概我们都知道这句话干了什么:将一个类(ObjectClass)实例化(创建一个对象)的过程。 那么也就是说,class关键字会在Python解释器解释到这里的时候创建一个对象(ObjectClass),而这个对象,拥有一个其他的一般对象没有的能力: 创建一个新的对象。

2. type 这个类

print(type('hello world'))
print(type(123456))
print(type(obj4))

<class 'str'>
<class 'int'>
<class '__main__.ObjectClass'>


我们会用 type() 来查看一个对象的类型,这是我们最常见的用法

newObject = type('newObject', (), {})
print(newObject)
obj5 = newObject()
print(obj5)

<class '__main__.newObject'> <__main__.newObject object at 0x102371198>


到这里,我们知道了这些东西:

  1. 类是一个对象
  2. type 可以创建类
  3. type 创建的对象拥有创建对象的能力(也就是类)

type 就是 Python 中所有类的元类(metaclass)

3. metaclass

元类 并不是某一个类的名字,它是一个概念,是一种Python的思想。

def MetaClass(name, bases, attrs):
    attrs['Author']='Megvii'
    return type(name, bases, attrs)

class InsClass(object, metaclass=MetaClass):
    Imethod='InsClass'
    
    def __init__(self, param):
        self.__param = param
        
obj6 = InsClass('test_instance')
print(obj6.Author)
print(dir(obj6))

Megvii
['Author', 'Imethod', '_InsClass__param', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

元类 metaclass 就是用来创建一个对象的,如果我们自定义元类,就可以将创建对象的过程拦截下来,从而对这个对象进行自定义。

道生一,一生二,二生三,三生万物

道是 type 一是 metaclass 二是类 三是对象 对象就是 Python 的所有

3.How && When

Singleton mode

class Singleton(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance

class Foo(metaclass=Singleton):
    def __init__(self):
        self.author = 'Megvii'
        
foo1=Foo()
foo2=Foo()

print(foo1 is foo2)
foo1.author = 'MEGVII'
print(foo2.author)

True
MEGVII

4. ORM (Object Relational Mapping)

首先定义 Field 类,它是所有 Fields 的父类

class Field(object):
    def __init__(self, name, col_type):
        self.name = name
        self.col_type = col_type
        
    def __str__(self):
        return "<{0}:{1}>".format(self.__class__.__name__, self.name)

派生出其他的 Field 类型,假定只有 CharField(字符串类型) 和 IntegerField(整数类型) 两种

class CharField(Field):
    def __init__(self, name, col_type='varchar(100)'):
        super(CharField, self).__init__(name, col_type)
        
class IntegerField(Field):
    def __init__(self, name, col_type='bigint'):
        super(IntegerField, self).__init__(name, col_type)

自定义元类,控制 Model 的创建过程

class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs):
        if name == 'Model':
            return super(ModelMetaClass, cls).__new__(cls, name, bases, attrs)
        mappings = dict()
        for key, val in attrs.items():
            if isinstance(val, Field):
                mappings[key] = val
        for key in mappings.keys():
            attrs.pop(key)      # 防止字段污染类属性本身
            
        attrs['__table__'] = name   # 保存表名为类名
        attrs['__mappings__'] = mappings  # 添加映射关系
        return super(ModelMetaClass, cls).__new__(cls, name, bases, attrs)

定义 Model 类,作为所有 Model 的父类

class Model(dict, metaclass=ModelMetaClass):    # 本质是一个自定义的 dict 类
    def __init__(self, **kwargs):
        super(Model, self).__init__(**kwargs)
    
    def __getattr__(self, key):
        try:
            return self[key]
        except Exception:
            raise AttributeError("'Model' object has no attribute {0}".format(key))
    
    def __setattr__(self, key, value):
        self[key] = value
        
    def sql_(self):
        fields = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v.name)
            args.append(getattr(self, k, None))
        return "INSERT INTO {table} ({fi}) VALUES ({va})".format(
            table=self.__table__, 
            fi=', '.join(fields), 
            va=', '.join(args)
        )
    
    def save(self):
        return self.sql_()

class User(Model):
    uid = IntegerField('uid')
    name = CharField('name')
    
user = User(uid='102740', name='zhangbo')

print(user.save())
print(dir(user))

INSERT INTO User (uid, name) VALUES (102740, zhangbo)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mappings__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__table__', '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'save', 'setdefault', 'sql_', 'update', 'values']

编辑于 2019-08-22 15:53