VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Python基础教程 >
  • python基础教程之PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(下)(3)

 

3.metaclass

a.使用元类
这个metaclass可以控制User2的形成。那么为什么可以控制类的形成呢?
metaclass相关博客: https://www.cnblogs.com/xybaby/p/7927407.html
 
b.元类的创建顺序
创建类的时候,会去找metaclass这个属性。最后都找不到metaclass的时候,才会调用type去创建类。
 
c.什么时候用元类
将创建user的new过程,托给元类。而不需要自己来做。

 

六. 实现简易django的orm

1.想要实现的效果

什么是orm?

即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。

具体的orm和django这种web框架的orm的设计自行查找资料哦~

我们想要实现类似于django中建立表对应的类的方法:

所以需要实现的有:
CharField类  IntField类  并且能实现save来insert。能把User类中定义的属性进行对应,Meta里的属性能被特定处理。

 

2.整个实现步骤

a.首先 IntField需要进行初始化、实现对参数进行检查。让InterField称为int属性描述符。同理,Charfield也是。

复制代码
class InterField:
    def __init__(self,value,min_length=None,max_length=None):
        self._value=value
        self._min_value=min_length
        self._max_value=max_length
        if self._min_value is not None:
            if not isinstance(self._min_value,numbers.Integral):
                raise ValueError("Value Must be Intergral")
            elif self._min_value < 0:
                raise ValueError("Value Must large than 0")


        if self._max_value is not None:
            if not isinstance(self._max_value,numbers.Integral):
                raise ValueError("Value must be Intergral")
            elif self._max_value <0 :
                raise  ValueError("Value must large than 0")
        if self.max_length < min_length:
            raise ValueError("Max must large than min ")

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value,numbers.Integral):
            raise ValueError("Not intergral")
        self._value=value
复制代码
复制代码
class CharField:
    def __init__(self,db_column,value,max_length=None):
        self._value=value
        self.db_column=db_column
        self._max_length=max_length
        if not max_length:
            raise ValueError("You must special the charfield length")

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        self._value=value
        if len(value) > self._max_length:
            raise ValueError("Value's length must less than max length")
复制代码

 

b.定义元类来设置特定的属性和方法

重点是,创建一个元类,来指定创建User的时候需要设定的很多属性,例如meta和save。在User类中是没有说明这些属性如何去设定、限制和用法的。
而我们需要在创建User的时候,注册进很多自己的属性到User里来。
比如django中,生成一个django中的表的时候,meta默认有很多属性是被设定了的,才会有我们建立一个表的类,只要设定key,value,django就自动帮忙把对应的属性和功能创建好了。
django中的大致设定:
复制代码
class ModelBase(type):

"""Metaclass for all models."""
 def __new__(cls, name, bases, attrs, **kwargs):
    super_new = super().__new__

    # Also ensure initialization is only performed for subclasses of Model
    # (excluding Model class itself).
    parents = [b for b in bases if isinstance(b, ModelBase)]
    if not parents:
        return super_new(cls, name, bases, attrs)

    # Create the class.
    module = attrs.pop('__module__')
    new_attrs = {'__module__': module}
    classcell = attrs.pop('__classcell__', None)
    if classcell is not None:
        new_attrs['__classcell__'] = classcell
        attr_meta = attrs.pop('Meta', None)
    # Pass all attrs without a (Django-specific) contribute_to_class()
    # method to type.__new__() so that they're properly initialized
    # (i.e. __set_name__()).
    contributable_attrs = {}
    for obj_name, obj in list(attrs.items()):
        if _has_contribute_to_class(obj):
            contributable_attrs[obj_name] = obj
        else:
            new_attrs[obj_name] = obj
    new_class = super_new(cls, name, bases, new_attrs, **kwargs)

    abstract = getattr(attr_meta, 'abstract', False)
    meta = attr_meta or getattr(new_class, 'Meta', None)
    base_meta = getattr(new_class, '_meta', None)

  app_label = None

# Look for an application configuration to attach the model to.
  app_config = apps.get_containing_app_config(module)

  if getattr(meta, 'app_label', None) is None:
   if app_config is None:
      if not abstract:
      raise RuntimeError(
        "Model class %s.%s doesn't declare an explicit "
        "app_label and isn't in an application in "
        "INSTALLED_APPS." % (module, name)
        )

    else:
      app_label = app_config.label
......
复制代码
我们模拟User直接设置它的元类为 modelMetaClass。并且再元类中实现__new__来对传进去的参数做处理。
首先用元类的__new__来打印传递到__new__中的参数。
相关教程