快捷搜索:
来自 网络数据库 2019-11-01 10:40 的文章
当前位置: 67677新澳门手机版 > 网络数据库 > 正文

的属性查找,自己动手写一个简易对象关系映射

mysql_pool.py

cached_property例子

咱俩再来看看上生机勃勃小说的这段代码。

import functools, time class cached_property(object): """ A property that is only computed once per instance and then replaces itself with an ordinary attribute. Deleting the attribute resets the property. """ def __init__(self, func): functools.update_wrapper(self, func) self.func = func def __get__(self, obj, cls): if obj is None: return self value = obj.__dict__[self.func.__name__] = self.func(obj) return value class TestClz(object): @cached_property def complex_calc(self): print 'very complex_calc' return sum(range(100)) if __name__=='__main__': t = TestClz() print '>>> first call' print t.complex_calc print '>>> second call' print t.complex_calc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import functools, time
class cached_property(object):
    """ A property that is only computed once per instance and then replaces
        itself with an ordinary attribute. Deleting the attribute resets the
        property. """
 
    def __init__(self, func):
        functools.update_wrapper(self, func)
        self.func = func
 
    def __get__(self, obj, cls):
        if obj is None: return self
        value = obj.__dict__[self.func.__name__] = self.func(obj)
        return value
 
class TestClz(object):
    @cached_property
    def complex_calc(self):
        print 'very complex_calc'
        return sum(range(100))
 
if __name__=='__main__':
    t = TestClz()
    print '>>> first call'
    print t.complex_calc
    print '>>> second call'
    print t.complex_calc

cached_property是一个non-data descriptor。在TestClz中,用cached_property装饰方法complex_calc,再次回到值是三个descriptor实例,所以在调用的时候从不应用小括号。

先是次调用t.complex_calc之前,obj(t)的__dict__中没有”complex_calc“, 依照查找顺序第三条,实施cached_property.__get__, 那个函数代用缓存的complex_calc函数总计出结果,而且把结果放入obj.__dict__。那么第二回访谈t.complex_calc的时候,依照查找顺序,第二条有限于第三条,所以就直接重临obj.__dict__[‘complex_calc’]。bottle的源码中还应该有四个descriptor,极度了得!

mysql_pool的配置:

references

  • Descriptor HowTo Guide,
  • Object attribute lookup in Python,
  • python __set__ __get__ 等解释,

    1 赞 3 收藏 1 评论

*__getattr__ 拦截点号运算。当对未定义的习性名称和实例进行点号运算时,就可以用属性名作为字符串调用那个主意。即便承继树能够找到该属性,则不调用此办法*

在上一小说最终,给出了豆蔻梢头段代码,就事关到descriptor与attribute lookup的难点。而get连串函数(__get__, __getattr__, __getattribute__) 也相当轻巧搞晕,本文就这一个主题素材差非常少总计一下。

区分__getattr__,__getattribute__

类属性查找

前方提到过,类的也是指标,类是元类(metaclass)的实例,所以类属性的探索顺序为主同上。分化在于第二步,由于Clz只怕有基类,所以是在Clz及其基类的__dict__”查找“attr,注意这里的追寻并不是直接重回clz.__dict__[‘attr’]。具体来讲,那第二步分为以下三种情状:

(2.1)如果clz.__dict__[‘attr’]是多个descriptor(不管是data descriptor依然non-data descriptor),都调用其__get__方法

(2.2)不然再次回到clz.__dict__[‘attr’]

那就解释了五个很有意思的题目:method与function的标题

Python

>>> class Widget(object): ... def func(self): ... pass ... >>> w = Widget() >>> Widget.__dict__ dict_proxy({'__dict__': <attribute '__dict__' of 'Widget' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Widget' objects>, '__doc__': None, 'func': <function func at 0x7fdc7d0d1668>}) >>> w.__dict__ {} >>> Widget.__dict__['func'] <function func at 0x7fdc7d0d1668> >>> Widget.func <unbound method Widget.func> >>>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> class Widget(object):
... def func(self):
... pass
...
>>> w = Widget()
>>> Widget.__dict__
dict_proxy({'__dict__': <attribute '__dict__' of 'Widget' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Widget' objects>, '__doc__': None, 'func': <function func at 0x7fdc7d0d1668>})
>>> w.__dict__
{}
 
 
>>> Widget.__dict__['func']
<function func at 0x7fdc7d0d1668>
>>> Widget.func
<unbound method Widget.func>
>>>

Widget是贰个之定义了一个func函数的类,func是类的属性,这么些也足以经过Widget.__dict__、w.__dict__看到。Widget.__dict__[‘func’]归来的是三个function,但Widget.func是贰个unbound method,即Widget.func并不肖似Widget.__dict__[‘func’],依据前边的类属性的拜访顺序,我们能够质疑,func是四个descriptor,那样才不会走到第2.2这种气象。验证如下:

Python

>>> dir(Widget.__dict__['func']) ['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

1
2
>>> dir(Widget.__dict__['func'])
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

新京葡娱乐场网址 1新京葡娱乐场网址 2

实例属性查找

固守python doc,要是obj是有个别类的实例,那么obj.name(以至等价的getattr(obj,’name’))首先调用__getattribute__。假若类定义了__getattr__方法,那么在__getattribute__抛出 AttributeError 的时候就能够调用到__getattr__,而对此描述符(__get__)的调用,则是爆发在__getattribute__此中的。官方网站文书档案是那样描述的

The implementation works through a precedence chain that gives data descriptors priority over instance variables, instance variables priority over non-data descriptors, and assigns lowest priority to __getattr__() if provided.

obj = Clz(), 那么obj.attr 顺序如下:

(1)借使“attr”是出现在Clz或其基类的__dict__中, 且attr是data descriptor, 那么调用其__get__方法, 否则

(2)如果“attr”出现在obj的__dict__中, 那么直接回到 obj.__dict__[‘attr’], 否则

(3)假如“attr”出今后Clz或其基类的__dict__中

(3.1)假若attr是non-data descriptor,那么调用其__get__方法, 否则

(3.2)返回 __dict__[‘attr’]

(4)如果Clz有__getattr__方法,调用__getattr__方法,否则

(5)抛出AttributeError

上面是测验代码:

#coding=utf-8 class DataDescriptor(object): def __init__(self, init_value): self.value = init_value def __get__(self, instance, typ): return 'DataDescriptor __get__' def __set__(self, instance, value): print ('DataDescriptor __set__') self.value = value class NonDataDescriptor(object): def __init__(self, init_value): self.value = init_value def __get__(self, instance, typ): return('NonDataDescriptor __get__') class Base(object): dd_base = DataDescriptor(0) ndd_base = NonDataDescriptor(0) class Derive(Base): dd_derive = DataDescriptor(0) ndd_derive = NonDataDescriptor(0) same_name_attr = 'attr in class' def __init__(self): self.not_des_attr = 'I am not descriptor attr' self.same_name_attr = 'attr in object' def __getattr__(self, key): return '__getattr__ with key %s' % key def change_attr(self): self.__dict__['dd_base'] = 'dd_base now in object dict ' self.__dict__['ndd_derive'] = 'ndd_derive now in object dict ' def main(): b = Base() d = Derive() print 'Derive object dict', d.__dict__ assert d.dd_base == "DataDescriptor __get__" assert d.ndd_derive == 'NonDataDescriptor __新京葡娱乐场网址 ,get__' assert d.not_des_attr == 'I am not descriptor attr' assert d.no_exists_key == '__getattr__ with key no_exists_key' assert d.same_name_attr == 'attr in object' d.change_attr() print 'Derive object dict', d.__dict__ assert d.dd_base != 'dd_base now in object dict ' assert d.ndd_derive == 'ndd_derive now in object dict ' try: b.no_exists_key except Exception, e: assert isinstance(e, AttributeError) if __name__ == '__main__': main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#coding=utf-8
class DataDescriptor(object):
    def __init__(self, init_value):
        self.value = init_value
 
    def __get__(self, instance, typ):
        return 'DataDescriptor __get__'
 
    def __set__(self, instance, value):
        print ('DataDescriptor __set__')
        self.value = value
 
class NonDataDescriptor(object):
    def __init__(self, init_value):
        self.value = init_value
 
    def __get__(self, instance, typ):
        return('NonDataDescriptor __get__')
 
class Base(object):
    dd_base = DataDescriptor(0)
    ndd_base = NonDataDescriptor(0)
 
 
class Derive(Base):
    dd_derive = DataDescriptor(0)
    ndd_derive = NonDataDescriptor(0)
    same_name_attr = 'attr in class'
 
    def __init__(self):
        self.not_des_attr = 'I am not descriptor attr'
        self.same_name_attr = 'attr in object'
 
    def __getattr__(self, key):
        return '__getattr__ with key %s' % key
 
    def change_attr(self):
        self.__dict__['dd_base'] = 'dd_base now in object dict '
        self.__dict__['ndd_derive'] = 'ndd_derive now in object dict '
 
def main():
    b = Base()
    d = Derive()
    print 'Derive object dict', d.__dict__
    assert d.dd_base == "DataDescriptor __get__"
    assert d.ndd_derive == 'NonDataDescriptor __get__'
    assert d.not_des_attr == 'I am not descriptor attr'
    assert d.no_exists_key == '__getattr__ with key no_exists_key'
    assert d.same_name_attr == 'attr in object'
    d.change_attr()
    print 'Derive object dict', d.__dict__
    assert d.dd_base != 'dd_base now in object dict '
    assert d.ndd_derive == 'ndd_derive now in object dict '
 
    try:
        b.no_exists_key
    except Exception, e:
        assert isinstance(e, AttributeError)
 
if __name__ == '__main__':
    main()

注意第50行,change_attr给实例的__dict__其间扩充了四个属性。通过内外两条print的输出如下:

  Derive object dict {‘same_name_attr’: ‘attr in object’, ‘not_des_attr’: ‘I am not descriptor attr’}

Derive object dict {‘same_name_attr’: ‘attr in object’, ‘ndd_derive’: ‘ndd_derive now in object dict ‘, ‘not_des_attr’: ‘I am not descriptor attr’, ‘dd_base’: ‘dd_base now in object dict ‘}

调用change_attr方法之后,dd_base既出现在类的__dict__(作为data descriptor), 也应时而生在实例的__dict__, 因为attribute lookup的循序,所以优先重回的依旧Clz.__dict__[‘dd_base’]。而ndd_base尽管出今后类的__dict__, 但是因为是nondata descriptor,所以优先再次来到obj.__dict__[‘dd_base’]。其他:line48,line56表明了__getattr__的作用。line49表明obj.__dict__优先于Clz.__dict__

既然自个儿要用数据库中的表,对应那一个主次中的类,那么笔者那几个类也应该有这么些类属性

在Python中,属性查找(attribute lookup)是比较复杂的,极度是涉及到描述符descriptor的时候。

新京葡娱乐场网址 3新京葡娱乐场网址 4

质量赋值

Python的品质赋值(attribute assignment)也会遭到descriptor(data descriptor)的影响,同期也会遭逢__setattr__函数的熏陶。当然Python中还会有一个setattr,setattr(x, ‘foobar’, 123)等价于x.foobar = 123,二者都叫attribute assignment。

先是探访__setattr__:

object.__setattr__(self, name, value)
Called when an attribute assignment is attempted. This is called instead of the normal mechanism

那什么是normal mechanism,简单的讲就是x.__dict__[‘foobar’] = 123,不管’foobar’早先是还是不是是x的习性(当然赋值之后就断定是了)。可是要是‘’foobar‘’是类属性,且是data descriptor,那么回先行调用__set__。大家来看八个例证:

class MaxValDes(object): def __init__(self, attr, max_val): self.attr = attr self.max_val = max_val def __get__(self, instance, typ): return instance.__dict__[self.attr] def __set__(self, instance, value): instance.__dict__[self.attr] = min(self.max_val, value) print 'MaxValDes __set__', self.attr, instance.__dict__[self.attr] class Widget(object): a = MaxValDes('a', 10) def __init__(self): self.a = 0 # def __setattr__(self, name, value): # self.__dict__[name] = value # print 'Widget __setattr__', name, self.__dict__[name] if __name__ == '__main__': w0 = Widget() w0.a = 123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MaxValDes(object):
    def __init__(self, attr, max_val):
        self.attr = attr
        self.max_val = max_val
 
    def __get__(self, instance, typ):
        return instance.__dict__[self.attr]
 
    def __set__(self, instance, value):
        instance.__dict__[self.attr] = min(self.max_val, value)
        print 'MaxValDes __set__', self.attr, instance.__dict__[self.attr]
 
class Widget(object):
    a = MaxValDes('a', 10)
    def __init__(self):
        self.a = 0
 
    # def __setattr__(self, name, value):
    #     self.__dict__[name] = value
    #     print 'Widget __setattr__', name, self.__dict__[name]
 
if __name__ == '__main__':
    w0 = Widget()
    w0.a = 123

输出如下:

Python

MaxValDes __set__ a 0 MaxValDes __set__ a 10

1
2
MaxValDes __set__ a 0
MaxValDes __set__ a 10

能够看出,就算Widget的实例也可以有三个‘a’属性,不过调用w.a的时候会调用类属性‘a’(二个descriptor)的__set__方法。若是不注释掉第18到第20行,输出如下

Python

Widget __setattr__ a 0 Widget __setattr__ a 123

1
2
Widget __setattr__ a 0
Widget __setattr__ a 123

可以见到,优先调用Widget 的__setattr__方法。因而:对于属性赋值,obj = Clz(), 那么obj.attr = var,依照那样的逐大器晚成:

  1. 如果Clz定义了__setattr__艺术,那么调用该方式,不然
  2. 假设“attr”是出新在Clz或其基类的__dict__中, 且attr是data descriptor, 那么调用其__set__方法, 否则
  3. 等价调用obj.__dict__[‘attr’] = var

新京葡娱乐场网址 5新京葡娱乐场网址 6

原版的书文出处: xybaby   

def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value

    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass


def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.

    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass


def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.

    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
  • python中一切都以对象,“everything is object”,满含类,类的实例,数字,模块
  • 任何object都是类(class or type)的实例(instance)
  • 假使三个descriptor只兑现了__get__艺术,大家称为non-data descriptor, 即使同不经常间贯彻了__get__ __set__咱俩誉为data descriptor。

2 也可以 user=User()

率先,我们知道:

元类概念回看(>>传送门点这里<<)

 新京葡娱乐场网址 7

五、基于pymysql的数据库操作类(单例)

操作类与指标的习性的增加补充:

 

新京葡娱乐场网址 8新京葡娱乐场网址 9

class Foo:
    x=1
    def __init__(self,y):
        self.y=y

    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')


    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #这就无限递归了,你好好想想
        # self.__dict__[key]=value #应该使用它

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)

#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)

#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)

#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

新京葡娱乐场网址 10新京葡娱乐场网址 11

新京葡娱乐场网址 12新京葡娱乐场网址 13

*__setattr__会堵住全部属性的的赋值语句。要是定义了这一个点子,self.arrt = value 就能够化为self,__setattr__("attr", value).那个须求小心。当在__setattr__形式内对品质进行赋值是,不可选择self.attr = value,因为她会再一次调用self,__setattr__("attr", value),则会形成无穷递归循环,最终变成仓库溢出极其。应该通过对质量字典做索引运算来赋值任何实例属性,约等于行使self.__dict__['name'] = value*

预备知识

DBUtils是Python的一个用于实现数据库连接池的模块

此连接池有两种连接模式:

    DBUtils提供两种外部接口:
    PersistentDB :提供线程专用的数据库连接,并自动管理连接。
    PooledDB :提供线程间可共享的数据库连接,并自动管理连接。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/05/15 10:44
# @Author  : MJay_Lee
# @File    : mysql_pool.py
# @Contact : limengjiejj@hotmail.com

from video_web_mysql.orm_pool import orm_pool
import pymysql

class Mysql_interface:
    def __init__(self):
        self.conn = orm_pool.POOL.connection()
        self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    def close_db(self):
        self.cursor.close()
        self.conn.close()

    def select(self,sql,args=None):
        self.cursor.execute(sql,args)
        re = self.cursor.fetchall()

        return re

    def execute(self,sql,args):
        try:
            self.cursor.execute(sql,args)
            affected = self.cursor.rowcount
        except BaseException as e:
            print(e)
        return affected


if __name__ == '__main__':
    ms = Mysql_interface()
    re = ms.select('select * from user where id = %s',1)
    print(re)

DBUtils模块  <<-----重点

新京葡娱乐场网址 14新京葡娱乐场网址 15

前三种,能够透过三番五遍字典dict来得以达成,第二种,用getattr和setattr:

补充:

ORM简介

单例 (>>传送门点这里<<)

# 在ModelsMetaclass中自定义拦截实例化对象的方法
class Models(dict,metaclass=ModelsMetaclass):
    # k,v形式的值
    def __init__(self,**kwargs):
        super().__init__(**kwargs)

    # 写存
    def __setattr__(self, key, value):
        self[key] = value

    # 读取
    def __getattr__(self, item):
        try:
            return self[item]
        except KeyError:
            raise ('没有该属性')

    @classmethod
    def select_one(cls,**kwargs):
        '''
        查一条
        :param kwargs:
        :return:
        '''
        key = list(kwargs.keys())[0]
        value = kwargs[key]

        # select * from user where id=%s
        sql = 'select * from %s where %s =?' % (cls.table_name,key)
        sql = sql.replace('?','%s')
        ms = mysql_singleton.Mysql_interface().singleton()
        re = ms.select(sql,value) # 得到re字典对象
        if re:
            # attrs = {'name':'lmj','password':123}
            # User(**attrs)
            # 相当于 User(name='lmj',password=123)
            return cls(**re[0])
        else:
            return

    @classmethod
    def select_many(cls, **kwargs):
        '''
        查多条
        :param kwargs:
        :return:
        '''
        ms = mysql_singleton.Mysql_interface().singleton()
        if kwargs:
            key = list(kwargs.keys())[0]
            value = kwargs[key]

            sql = 'select * from %s where %s =?' % (cls.table_name, key)
            sql = sql.replace('?', '%s')
            re = ms.select(sql, value)  # 得到re字典对象
        else:
            sql = 'select * from %s' % (cls.table_name)
            re = ms.select(sql)
        if re:
            obj_list = [cls(**r) for r in re]
            return obj_list
        else:
            return


    def update(self):
        ms = mysql_singleton.Mysql_interface().singleton()
        # update user set name = ?,password = ? where id = ?

        filed_data = [] # name = ?,password = ?
        pr = None
        args = [] # 字段的值
        for k,v in self.mappings.items():
            if v.primary_key:
                pr = getattr(self,v.name,v.default)
            else:
                filed_data.append(v.name   '=?')
                args.append(getattr(self,v.name,v.default))

        sql = 'update %s set %s where %s = %s' % (self.table_name,','.join(filed_data),self.primary_key,pr)
        sql = sql.replace('?','%s')
        ms.execute(sql,args)


    def save(self):
        ms = mysql_singleton.Mysql_interface().singleton()
        # insert into user(name,password) values (?,?)
        field_data = []
        args = []
        value_data = []
        for k,v in self.mappings.items():
            if not v.primary_key:
                field_data.append(v.name)
                args.append(getattr(self,v.name,v.default))
                value_data.append('?')

        sql = 'insert into %s(%s) VALUES (%s)' % (self.table_name,','.join(field_data),','.join(value_data))
        sql = sql.replace('?','%s')
        ms.execute(sql,args)

 

from DBUtils.PooledDB import PooledDB
import pymysql

POOL = PooledDB(
    creator=pymysql,  # 使用链接数据库的模块
    maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
    mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
    maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
    maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
    blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
    maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
    setsession=[],  # 开始会话前执行的命令列表。
    ping=0,
    # ping MySQL服务端,检查是否服务可用。
    host='127.0.0.1',
    port=3306,
    user='root',
    password='123456',
    database='youku',
    charset='utf8',
    autocommit = True
)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/05/15 10:44
# @Author  : MJay_Lee
# @File    : mysql_singleton.py
# @Contact : limengjiejj@hotmail.com

import pymysql

class Mysql_interface:
    __instense = None
    def __init__(self):
        self.conn = pymysql.connect(
            host = '127.0.0.1',
            port = 3306,
            user = 'root',
            password = '123456',
            charset = 'utf8',
            database = 'youku',
            autocommit = True
        )
        self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    def close_db(self):
        self.cursor.close()
        self.conn.close()

    def select(self,sql,args):
        self.cursor.execute(sql,args)
        re = self.cursor.fetchall()

        return re

    def execute(self,sql,args):
        try:
            self.cursor.execute(sql,args)
            affected = self.cursor.rowcount
        except BaseException as e:
            print(e)
        return affected

    @classmethod
    def singleton(cls):
        if not cls.__instense:
            cls.__instense = cls()
        return cls.__instense



if __name__ == '__main__':
    ms = Mysql_interface()
    re = ms.select('select * from user where id = %s',1)
    print(re)
# 在ModelsMetaclass中自定义拦截实例化对象的方法
class Models(dict,metaclass=ModelsMetaclass):
    # k,v形式的值
    def __init__(self,**kwargs):
        super().__init__(**kwargs)

    # 写存
    def __setattr__(self, key, value):
        self[key] = value

    # 读取
    def __getattr__(self, item):
        try:
            return self[item]
        except KeyError:
            raise ('没有该属性')
class ModelsMetaclass(type):
    def __new__(cls,name,bases,attrs):

        if name == 'Models': #
            return type.__new__(cls, name, bases, attrs)
        table_name = attrs.get('table_name', None) #字典取值,中括号或.get
        if not table_name:
            table_name = name

        primary_key = None
        mappings = dict()
        for k, v in attrs.items():
            if isinstance(v, Field):  # v 是不是Field的对象
                mappings[k] = v
                if v.primary_key: # v是基类对象,即判断该字段的主键

                    # 找到主键
                    if primary_key:
                        raise TypeError('主键重复:%s' % k)
                    primary_key = k

        for k in mappings.keys():
            attrs.pop(k) # 执行完此步后,attrs中只剩余有__属性__
        if not primary_key:
            raise TypeError('没有主键')
        attrs['table_name'] = table_name
        attrs['primary_key'] = primary_key
        attrs['mappings'] = mappings
        return type.__new__(cls, name, bases, attrs)

1、在实例化二个user对象的时候,能够user=User(name='lqz',password='123')

 

fuckorm的黄金年代体化源码:

 反射(update和save四个成效代码里,拼接SQL语句时,给参数赋值时时必要用上): 

新京葡娱乐场网址 16新京葡娱乐场网址 17

本文由67677新澳门手机版发布于网络数据库,转载请注明出处:的属性查找,自己动手写一个简易对象关系映射

关键词: