Python--type (), Metaclass meta-class, and streamlined ORM framework

Source: Internet
Author: User
Tags class definition

1. Type () function
The #type () function can either return the type of an object, or create a new type,  # For example, we can create a Hello class with the type () function without having to pass class hello (object) ... Definition:    def fn (self,name= ' world '):  #先定义函数      print (' Hello,%s. '%name)  #开始用type ()  hello = type (' Hello ', (object,), Dict (HELLO=FN)  # Creates a Hello class  #要创建一个class对象, and the type () function passes 3 arguments in turn:  #class的名称;  #继承的父类集合, Note that Python supports multiple inheritance, and if there is only one parent class, don't forget the single-element notation of tuple;  

 

The #type () function can either return the type of an object, or create a new type, # For example, we can create a Hello class with the type () function without having to pass class hello (object) ... Definition: DEF fn (self,name= ' world '):  #先定义函数    print (' Hello,%s. '%name) #开始用type () Hello = type (' Hello ', (object), Dict (HELLO=FN)  # Create Hello class# to create a class object, the type () function passes in 3 arguments: #class的名称; #继承的父类集合, note that Python supports multiple inheritance, if there is only one parent class, Don't forget the single-element notation of the tuple, #class的方法名称与函数绑定, here we bind the function fn to the method name hello.

  

if __name__ = = ' __main__ ':      h = hello ()      H.hello () print (type (      hello))      print (Type (h))  

if __name__ = = ' __main__ ':
h = Hello ()
H.hello ()
Print (type (hello))
Print (Type (h))

Hello, world.  <class ' type ' >  <class ' __main__. Hello ' >  

Hello, world.
<class ' type ' >
<class ' __main__. Hello ' >

2, Metaclass Yuan class
#metaclass   Meta   -Class Metaclass allows you to create classes or modify Class  Listmetaclass (Type):      def __new__ (CLS, name,bases,attrs):          attrs[' Add ' = Lambda self,value:self.append (value) #增加了add () method          return type.__new__ (cls,name,bases,attrs)  class MyList (list,metaclass=listmetaclass):      pass  #__new__ () method The parameters received are:    #1, the object of the class currently being created;  2, the name of the class,  #3, class inheritance of the parent class collection,  #4, the collection of methods of the class.      #元类一般情况不常用, but always encounter the need to modify the class definition through Metaclass. ORM is a typical example.  #ORM全称 "Object Relational Mapping", which is the objects-relational mapping, is to map a row of a relational database to an object, # that is, a  class that corresponds to a table, which makes it easier to write code without having to manipulate SQL statements directly.  #要编写一个ORM框架, all classes can only be defined dynamically, because only the user can define the corresponding class based on the structure of the table.  

  

#metaclass   Meta   -Class Metaclass allows you to create classes or modify Class Listmetaclass (type):    def __new__ (CLS, name,bases,attrs):        attrs[' Add ' = Lambda self,value:self.append (value) #增加了add () method        return type.__new__ (Cls,name,bases,attrs) class MyList (List,metaclass=listmetaclass):    the Pass#__new__ () method takes the following parameters: #1, the object of the class that is currently being prepared, #2, the name of the class, the collection of parent classes that #3, class inheritance, #4, The collection of methods for the class. #元类一般情况不常用, but always encounter the need to modify the class definition through Metaclass. ORM is a typical example. #ORM全称 "Object Relational Mapping", which is the objects-relational mapping, is to map a row of a relational database to an object, # that is, a class that corresponds to a table, which makes it easier to write code without having to manipulate SQL statements directly. #要编写一个ORM框架, all classes can only be defined dynamically, because only the user can define the corresponding class based on the structure of the table.

  

if __name__ = = ' __main__ ':      l = MyList ()      L.add (2)  #增加了add () method      L.add (3)      print (L)  

if __name__ = = ' __main__ ':
L = MyList ()
L.add (2) #增加了add () method
L.add (3)
Print (L)

[2, 3]
3. Streamline the ORM Framework
#开始编写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 St Ringfield (Field): def __init__ (Self,name): Super (Stringfield,self). __init__ (name, ' varchar ') class in Tegerfield (Field): def __init__ (Self,name): Super (Integerfield,self). __init__ (name, ' bigint ') #下一步, is to write the most complex m Odelmetaclass: Class Modelmetaclass (type): Def __new__ (CLS, name,bases,attrs): if name = = ' Model ': #排除掉对M Changes to the Odel class; return type.__new__ (cls,name,bases,attrs) print (' Found Model:%s '%name) mappings                  = Dict () for k,v in Attrs.items (): #查找定义的类的所有属性, if Isinstance (V,field): #如果找到一个Field属性,          Print (' Found mapping:%s ==>%s '% (k, v)) mappings[k] = v #就把它保存到一个__mappings__的dict中 For K in Mappings.keys (): Attrs.pop (k) #同时从类属性中删除该Field属性, otherwise, it is easy to cause a run-time error (the attribute of the instance obscures the property with the same name as the Class); attrs[' __mappings__ ' = mappings # Save attribute and column Mappings attrs[' __table__ ' = name # Assuming that the table name and class name match the table name to __table__ return type.__new__ (cls,name,bases , attrs) #基类Model class Model (dict,metaclass=modelmetaclass): def __init__ (self,**kw): Super (Model,self). __init__ (**KW) def __getattr__ (self, item): #没有找到的属性, right here to find Try:return Self[item] Exc EPT keyerror:raise Attributeerror (r "Model ' object have no attrs: '%s '"%item) def __setattr__ (self, ke          Y, 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 (Field    s), ', '. Join (params))      Print (' sql:%s '% sql) print (' ARGS:%s '% str (args)) #子类User # defines the class's attribute-to-column mapping: Class User (Model): ID = Integerfield (' id ') name = Stringfield (' username ') email = stringfield (' email ') password = Stringfield (' P   Assword ') Age = Integerfield (' age ')

#开始编写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 ')
The #下一步 is to write the most complex modelmetaclass:
Class Modelmetaclass (Type):
Def __new__ (CLS, name,bases,attrs):
If name = = ' Model ': #排除掉对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): #如果找到一个Field属性,
Print (' Found mapping:%s ==>%s '% (k, v))
Mappings[k] = v #就把它保存到一个__mappings__的dict中
For k in Mappings.keys ():
Attrs.pop (k) #同时从类属性中删除该Field属性, otherwise, it is easy to create a run-time error (the attribute of the instance obscures the same name property of the Class);
attrs[' __mappings__ ' = mappings # Save the mappings of properties and columns
attrs[' __table__ ' = name # Assuming that the table name and class name match the table name to __table__
Return type.__new__ (Cls,name,bases,attrs)

#基类Model
Class Model (Dict,metaclass=modelmetaclass):
def __init__ (self,**kw):
Super (Model,self) __init__ (**kw)
def __getattr__ (self, item): #没有找到的属性, find it here.
Try
return Self[item]
Except Keyerror:
Raise Attributeerror (R "Model ' object has no attrs: '%s '"%item)

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) '% (%s) '% (self.__table__, ', '. Join (Fields), ', '. Join (params))
Print (' sql:%s '% sql)
Print (' args:%s '% str (args))

#子类User
# define the property-to-column mappings for the class:
Class User (Model):
id = integerfield (' id ')
Name = Stringfield (' username ')
email = stringfield (' email ')
Password = Stringfield (' password ')
Age = Integerfield (' age ')

 

When the user defines one class User(Model) , the Python interpreter first looks in the definition of the current class, and User metaclass if it is not found, continues to look in the parent class, finds it, Model creates the metaclass Model metaclass ModelMetaclass User class with the definition in In other words, metaclass can be implicitly inherited to subclasses, but subclasses cannot feel it themselves.


In ModelMetaclass , there are a few things that have been done:


    1. Eliminate the modification of the Model class;


    2. Finds all the properties of the defined class in the current class (for example User ), if a field property is found, it is saved to a __mappings__ dict, and the field property is removed from the class attribute, otherwise it is prone to run-time errors (the attribute of the instance obscures the same name property of the Class);


    3. Save the table name to the table name __table__ , which is simplified to the class name by default.


In a Model class, you can define various methods of manipulating the database, such as,,, and save() so on delete() find() update .


We implemented the save() method to save an instance to the database. A statement can be constructed because of a table name, a property-to-field mapping, and a collection of property values INSERT .

To write code try:  
if __name__ = = ' __main__ ':      u = User (id = 12345,name = ' john ', email = ' [email protected] ', password = ' 666666 ')      U.ag E =      U.save ()  

if __name__ = = ' __main__ ':
U = User (id = 12345,name = ' john ', email = ' [email protected] ', password = ' 666666 ')
U.age = 12
U.save ()

Found model:user  Found mapping:id ==> <IntegerField:id> Found mapping:name ==> <stringfield  : username>  Found mapping:email ==> <StringField:email>  Found Mapping:password ==> < stringfield:password>  Found mapping:age ==> <IntegerField:age>  sql:insert into User (id,username , email,password,age) VALUES (?,?,?,?,?)  ARGS: [12345, ' John ', ' [email protected] ', ' 666666 ', 12]  

Found Model:user
Found Mapping:id ==> <IntegerField:id>
Found mapping:name ==> <StringField:username>
Found Mapping:email ==> <StringField:email>
Found Mapping:password ==> <StringField:password>
Found mapping:age ==> <IntegerField:age>
Sql:insert into User (id,username,email,password,age) VALUES (?,?,?,?,?)
ARGS: [12345, ' John ', ' [email protected] ', ' 666666 ', 12]

 

That is, the class property of the user class that is mapped to the column can be added to the SQL statement, and the class property of the mapped to the column is not done: such as height, it is filtered out, the height of the field that implements the database column can be customized
if __name__ = = ' __main__ ':      u = User (id = 12345,name = ' john ', email = ' [email protected] ', password = ' 666666 ', height =      # u.age =      U.save ()  

if __name__ = = ' __main__ ':
U = User (id = 12345,name = ' john ', email = ' [email protected] ', password = ' 666666 ', height = 180)
# u.age = 12
U.save ()

Found model:user  Found mapping:id ==> <IntegerField:id> Found mapping:name ==> <stringfield  : username>  Found mapping:email ==> <StringField:email>  Found Mapping:password ==> < stringfield:password>  Found mapping:age ==> <IntegerField:age>  sql:insert into User (id,username , email,password,age) VALUES (?,?,?,?,?)  ARGS: [12345, ' John ', ' [email protected] ', ' 666666 ', None]  


Found Model:user
Found Mapping:id ==> <IntegerField:id>
Found mapping:name ==> <StringField:username>
Found Mapping:email ==> <StringField:email>
Found Mapping:password ==> <StringField:password>
Found mapping:age ==> <IntegerField:age>
Sql:insert into User (id,username,email,password,age) VALUES (?,?,?,?,?)
ARGS: [12345, ' John ', ' [email protected] ', ' 666666 ', None]


Even if the height parameter is passed at initialization time, it is still filtered out, and the class attribute of the mapping to the column is defined as age, which, even if not assigned, is defaulted to none and added to the database. Note: You can see that save()Method has printed out the executable SQL statement, as well as the parameter list, just to really connect to the database, execute the SQL statement, you can complete the real function. The following warehousing operations, as well as the rest of the deletion check operation can be resolved by itself.

Python--type (), Metaclass meta-class, and streamlined ORM framework

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.