zoukankan      html  css  js  c++  java
  • python中的元类浅析

    本文主要参考  刘羽冲 的文章,原文地址 点击链接, 原文讲的很生动,我这篇主要做笔记。

    1 python的类型衍生

      1 type: python所有类型的起源

      2 元类 metaclass: 生成类的父

      3 类 class: 生成实例的父

      4 实例 instance: 对象实例

      5 各种方法属性

    2 两种创建类的方式

    # 第一种方式
    class Foo(object):
    
        def add_one(self, x):
            return x+1
    
    print Foo().add_one(1)
    
    # out: 2
    # 第二种方式
    Foo = type('Foo', (object,), dict(add_one=lambda self, x: x+1))
    
    print Foo().add_one(1)
    
    # out: 2

    第一种创建方式是: 类---->实例--->方法

    第二种创建方式是:type---->类---->实例--->方法

    现在我们来看第二种 type方式,这里面有三个参数分别是 类名继承的父类类方法

    其实这三个参数也可以叫,我是谁,我从哪里来,我要干什么

    3 元类metaclass

     元类更像是“天赋”。由元类创建出的类可以继承这种天赋。

    如果说类是决定对象的,那么元类就是决定类的

    # 由type创建元类,必须要继承type
    class MetaClassFoo(type):
    
        # 由元类创建类也遵循 名字;继承;方法
        def __new__(cls, name, base, attrs):
            # 天赋,赋予给通过该元类创建的类
            attrs['func'] = lambda self: 'im %s and i have func!' % self.name
            return type.__new__(cls, name, base, attrs)
    
    
    # 由元类创建类
    class Foo(object):
    
        __metaclass__ = MetaClassFoo
    
        def __init__(self):
            self.name = 'WWW'
    
    
    # 由类创建实例,并生成方法
    print Foo().func()
    
    
    # out: im WWWand i have func!

    4 元类的适用场合

    大部分场合不需要用元类。

    元类主要适用在框架的编写,比如ORM对象关系映射。下面是一个ORM示例

    # 该类是定义数据类型类型的父类
    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)
    
    
    # 创建Model类
    class Model(dict):
    
        __metaclass__ = ModelMetaclass
    
        def __init__(self, **kwarg):
            super(Model, self).__init__(**kwarg)
    
        def __getattr__(self, key):
            try:
                return self[key]
            except KeyError:
                raise AttributeError("'Model' object has no attribute '%s'" % key)
    
        def __setattr__(self, key, value):
            self[key] = value
    
        # 模拟建表操作
        def save(self):
            fields = []
            args = []
            for k, v in self.__mappings__.items():
                fields.append(v.name)
                args.append(getattr(self, k, None))
            sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join([str(i) for i in args]))
            print('SQL: %s' % sql)
            print('ARGS: %s' % str(args))
    
    
    # 继承Model类的表类
    class User(Model):
        # 定义类的属性到列的映射:
        id = IntegerField('id')
        name = StringField('username')
        email = StringField('email')
        password = StringField('password')
    
    
    # 表对象
    u = User(id=12345, name='Batman', email='batman@nasa.org', password='iamback')
    u.save()
    View Code
    # out
    Found model: User
    Found mapping: email ==> <StringField:email>
    Found mapping: password ==> <StringField:password>
    Found mapping: id ==> <IntegerField:id>
    Found mapping: name ==> <StringField:username>
    SQL: insert into User (password,email,username,id) values (iamback,batman@nasa.org,Batman,12345)
    ARGS: ['iamback', 'batman@nasa.org', 'Batman', 12345]
    View Code
  • 相关阅读:
    《从0开始学架构》——学习笔记(基础篇和高性能篇)
    Oracle的数据并发与一致性详解(下)
    Oracle的数据并发与一致性详解(上)
    关于oracle的缓冲区机制与HDFS中的edit logs的某些关联性的思考
    分布式锁的两种实现方式(基于redis和基于zookeeper)
    hadoop配置文件详解系列(二)-hdfs-site.xml篇
    hadoop配置文件详解系列(一)-core-site.xml篇
    【管理心得之四十六】你呀,少肺
    【管理心得之四十五】你呀,没心
    【管理心得之四十四】独立冲突之外,你做不到
  • 原文地址:https://www.cnblogs.com/fuzzier/p/7799411.html
Copyright © 2011-2022 走看看