zoukankan      html  css  js  c++  java
  • Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了。

    Python面向对象之类的方法和属性

    本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django。

    在Python中有一个type类,所有的类都是基于type类生成的,可谓万物之母。

    如此广袤无垠的python生态圈,都是由type产生出来的。

    Python面向对象总计包含五大部分:

    常用部分:

    3.class(类,或者叫实例生成器)

    4.instance(实例)

    5.实例的各种属性与方法,我们平常使用python时,调用的就是它们。

    不常用部分(类从何而来):

    1.type

    2.metaclass(元类,或者叫类生成器)

     两种方式创建类:

    # 创建一个Hello类,拥有属性say_hello
    class Hello():
        def say_hello(self, name='gregory'):
            print( 'Hello, %s.'% name)
    # 从Hello类创建一个实例hello
    hello =Hello()
    # 使用hello调用方法say_hello
    hello.say_hello()
    
    def func(self, name='gregory'):
    # 创建函数func
        print('Hi, %s.'% name)
    Hi= type('Hi', (object,), dict(say_hello=func))
    # 通过type创建Hi class
    hello=Hi()
    hello.say_hello()

    效果一样的。

    Hi= type('Hi', (object,), dict(say_hello=func))

    第一个参数: 类名。我是谁。

    第二个参数:当前类的基类。我从哪里来,也就是我的“父类”,以上实例中我的父类是“object”——python中一种非常初级的类。

    第三个参数:类的成员。我要到哪里去,将需要调用的方法和属性包含到一个字典里,再作为参数传入。以上实例中,say_hello方法包装进了字典中。

    type可以直接生成类(class),但也可以先生成元类(metaclass),再使用元类批量定制类(class)。

    元类均被命名后缀为Metalass,元类的生命周期:

    class SayMetaClass(type):
        #元类是由“type”衍生而出,所以父类需要传入type。
        def __new__(cls, name, bases, attrs):
            #元类的操作都在 __new__中完成,它的第一个参数是将创建的类,之后的参数即是三大永恒命题:类名,基类,类的成员。
    
            attrs['say_'+ name] =lambda self, value, saying=name:print(saying + ','+ value +'!')
            #创造属性和方法,由元类创建的类叫“Hello”,那创建时就自动有了一个叫“say_Hello”的类方法
            # 然后又将类的名字“Hello”作为默认参数saying,传到了方法里面。
            # 然后把hello方法调用时的传参作为value传进去,最终打印出来。
    
            return type.__new__(cls, name, bases, attrs)
            #传承类名,父类,属性
    
    class Hello(object, metaclass =SayMetaClass):
        # 创建类,通过元类创建的类,第一个参数是父类,第二个参数是metaclass
        pass
    
    hello =Hello()# 创建实列
    hello.say_Hello( 'gregory')# 调用实例方法
    
    class Nihao(object,metaclass=SayMetaClass):
        pass
    
    nihao=Nihao()
    nihao.say_Nihao("greg 李")

    应用:Django的核心思想是“Object Relational Mapping”,即对象-关系映射,简称ORM。

    这是Django的一大难点,但学完了元类,一切变得清晰。你对Django的理解将更上一层楼!

    通过元类创建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)
    
    
    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))
    
    
    class User(Model):
        # 定义类的属性到列的映射:
        id = IntegerField('id')
        name = StringField('username')
        email = StringField('email')
        password = StringField('password')
    
    u = User(id=12345, name='Gregory', email='292409083@qq.com', password='iamgreg')
    u.save()

    这是Django中的Model版块核心原理!

    运行结果:

    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 (12345,Gregory,292409083@qq.com,iamgreg)
    ARGS: [12345, 'Gregory', '292409083@qq.com', 'iamgreg']
  • 相关阅读:
    Flutter-路由
    写一个底部Tabs导航动态组件
    实例:Flutter布局01
    HTTP报文
    HTML文本的各种属性
    HTML必要简介和基础
    MySQL8.0.23安装超详细傻瓜式
    从一个HTTP请求来研究网络分层原理
    MySQL的增删改查
    MySQL常用数据类型有哪些?
  • 原文地址:https://www.cnblogs.com/ningxin18/p/7787518.html
Copyright © 2011-2022 走看看