1.1 using enumerations
based on Enum class enumeration of implementations
>>> fromenum Import Enum
>>> month = Enum (' Month ', (' Jan ', ' Feb ', ' Mar ', ' Apr ', ' may ', ' June ', ' Jul ', ' April ', ' Sep ', ' Oct ', ' Nov ', ' Dec '))
>>> for Name, Member Inmonth.__members__.items ():
... print (name, ' = = ', member, ', ', Member.value)
...
Jan = Month.jan, 1
Feb = Month.feb, 2
Mar = Month.mar, 3
APR = MONTH.APR, 4
May = Month.may, 5
June = Month.jun, 6
Jul = Month.jul, 7
Month.aug, 8
Sep = month.sep, 9
OCT = month.oct, 10
Nov = Month.nov, 11
Dec = Month.dec, 12
The Value property is an int constant that is automatically assigned to a member , and is counted by default starting at 1 .
>>> Month.jun
<Month.Jun:6>
>>> Month.Jun.value
6
the exact control of the enumeration type can be Enum derivation Custom class
>>> from enum import enum, unique
>>> @unique- decorator check for duplicates
... class Weekday (Enum):
... Sun = 0
... Mon = 1
... Tue = 2
... Wed = 3
... Thu = 4
... Fri = 5
... Sat = 6
...
>>> Weekday (1)
<Weekday.Mon:1>
>>> Weekday (5)
<Weekday.Fri:5>
>>>weekday[' Sun ']
<Weekday.Sun:0>
>>> Weekday.sun
<Weekday.Sun:0>
>>>weekday.sun.value
0
>>> Weekday (7)
Traceback (most recent):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.5/enum.py", line 235, in __call__
Return cls.__new__ (CLS, value)
File "/usr/local/lib/python3.5/enum.py", line 470, in __new__
Raise ValueError ("%r is not a valid%s"% (value,cls.__name__))
Valueerror:7 is not a valid Weekday
1.2 using meta-classes1.2.1 Type ()
The biggest difference between dynamic and static languages is the definition of functions and classes, not defined at compile time, but dynamically created at run time.
define a hello.py module
Class Hello (object):
def hello (self, name= ' world '):
Print (' Hello,%s. '% name)
Called in the python interpreter
>>> from Hello import Hello
>>> h = Hello ()
>>> H.hello ()
Hello, world.
>>> print (Type (Hello))--type type
<class ' type ' >
>>> Print (Type (h))--class Hello type
<class ' Hello. Hello ' >
The definition of class is created dynamically at run time, and the method of creating class is using the type () function .
>>> deffn (self, name = ' World '):
... print (' Hello,%s '% name)
...
>>> hello= type (' Hello ', (object,), dict (hello = fn))
>>> h = Hello ()
>>> H.hello ()
Hello, World
>>> print (Type (Hello))
<class ' type ' >
>>> Print (Type (h))
<class ' __main__. Hello ' >
to create a class object, thetype () function passes through 3 parameters in turn :
1. Name of class ;
2. inherit the collection of parent classes , note that Python supports multiple inheritance, if there is only one parent class, do not forget the tuple 's single-element notation ;
>>> T = (1)
>>> type (T)
<class ' int ' >
>>> T = (1,)
>>> type (T)
<class ' tuple ' >
3.class the method name and function binding , here we bind the function fn to the method name Hello .
1.2.2 Metaclass
Metaclass, literal translation is a meta-class , the simple explanation is:metaclass is the premise of the class.
define The Metaclass first, then create the class, and finally create the instance.
under normal circumstances, it is seldom used to metaclass.
first define Listmetaclass
>>> class Listmetaclass(type): #metaclass is a template for a class that must derive from type
... def __new__ (CLS, name, bases, Attrs):
... attrs[' add ' = lambda self, vealue:self.append (value)-- definition of method
... return type.__new__ (CLS, name, bases, Attrs)
...
>>>
>>> class Mylist (list, metaclass = Listmetaclass):
... pass
...
>>> L = Mylist ()
>>> L
[]
>>> L.add (1)
>>> L
[1]
When creating MyList, the Python interpreter is created by listmetaclass.__new__ () , where we can modify the Metaclass The definition of adding new methods to achieve the added functionality.
__new__ () Method the parameters received are in turn:
1. object of the class currently being prepared for creation;
2. the name of the class;
3. collection of Class-inherited parent classes;
4. a collection of methods for the class.
1.2.2.1 Orm
That this part of the content is more difficult to understand .
starting with the introduction of Metaclass, it is mentionedthat metaclass use few scenes, and ORM scenarios are a typical example. As a DBA, I think this skill needs to be mastered.
ORM full name "object relationalmapping", that is, objects- relational mapping, is to map a row of the relational database to an object, that is, a class corresponding to a table, so that the code is easier to write, do not directly manipulate SQL statement.
to write a ORM Framework, all classes can only be defined dynamically, because only the user can define the corresponding class according to the structure of the table.
let's try to write a ORM Framework.
The first step in writing the underlying module is to write the calling interface first. For example, if the user uses this ORM framework and wants to define a user class to manipulate the corresponding database table User, we expect him to write this code:
Class User (Model):
# Define the property-to-column mappings for the class:
id = integerfield (' id ')
Name = Stringfield (' username ')
email = stringfield (' email ')
Password = Stringfield (' password ')
# Create an instance:
U = User (id=12345, name= ' Michael ', email= ' [email protected] ', password= ' my-pwd ')
# Save to database:
U.save ()
where the parent class The Model and attribute types Stringfield,Integerfield are provided by the ORM framework, and the remaining magic methods such as Save () are all Metaclass automatic completion. Although Metaclass is more complex to write, the user of ORM is surprisingly simple to use.
now, let's do this by pressing the interface above ORM.
first to define Field class, which is responsible for saving the name and field type of the database table:
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)
in the based on field, further define various types of field, such as Stringfield, Integerfield, etc.:
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 next step is to write the most complex the Modelmetaclass:
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 # Save the mappings of properties and columns
attrs[' __table__ ' = name # Assuming the table name and class name match
Return type.__new__ (CLS, name, bases, Attrs)
and base class Model:
Class Model (Dict,metaclass=modelmetaclass):
def __init__ (self, **kw):
Super (Model, self). __init__ (**KW)
Def__getattr__ (self, key):
Try
return Self[key]
Except Keyerror:
Raise Attributeerror (R "Model ' object has no attribute '%s '"%key)
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))
When a user defines a class user (Model) ,the Python interpreter first finds metaclass in the definition of the current class user, and if it is not found, Continue to look for metaclass in the parent model andfind it, using the metaclass defined in model Modelmetaclass To create the User class, that is,metaclass can be implicitly inherited to subclasses, but the subclass cannot feel it.
in the In Modelmetaclass, there are a few things that have been done:
rule out the right modification of the Model class;
in the current class (e.g. User) To find all the properties of the defined class, if a field property is found, save it to a __mappings__ dict , and remove the field from the Class property property, which can cause a run-time error (the property of the instance obscures the property of the same name);
Save the table name to __table__ , which is simplified to the table name by default to the class name.
in the In the Model class, you can define various ways to manipulate the database, such as Save (),Delete (), find (), update,and so on .
we implemented the Save () method to save an instance to the database. Because of the table name, property-to-field mappings, and the collection of property values, you can construct an INSERT statement.
To write code try:
U = User (id=12345, name= ' Michael ', email= ' [email protected] ', password= ' my-pwd ')
U.save ()
The output is as follows:
Found Model:user
Found Mapping:email ==><stringfield:email>
Found Mapping:password ==><stringfield:password>
Found Mapping:id ==><integerfield:uid>
Found Mapping:name ==><stringfield:username>
Sql:insert into User (password,email,username,id) VALUES (?,?,?,?)
ARGS: [' my-pwd ', ' [email protected] ', ' Michael ', 12345]
As you can see,the Save () method has printed out the executable SQL statement, as well as the parameter list, so that you can actually connect to the database and execute the SQL statement to complete the function.
With less than a few lines of code, we implemented a streamlined ORM framework through Metaclass .
Python advanced programming for objects--using enumerations and meta classes