1、首先我们要知道:

对象是由类创建的,而类是由type类创建的

所以创建类有两个方法:

class Foo(object):pass# 类名,继承关系,属性
Foo = type('Foo',(object,),{})

上面第一种方法也是默认用type来创建类的,我们就可以理解为类其实就是type的一个对象

当类名()这样加括号的时候,会首先调用type的_ _call_ _方法,在这个方法里会调用类的_ _new_ _方法来创建一个裸着的对象,也就是开辟内存空间,但是没有任何东西,继而继续调用执行类的_ _init_ _方法来给对象封装一些属性

补充一下:对象()这样加括号就会调用类的_ _call_ _方法

2、metaclass就可以指定我们自定义的type类,当用类名()时就会从我们定义的metaclass参数值的类中调用_ _call_ _方法,要依次调用_ _new_ _和_ _init_ _方法,返回对象

这样做的一个好处是我们在实例对象时先是_ _new_ _方法再是_ _init_ _方法,用了我们自定义type类的时候我们就可以在new方法和init方法之间就可以做一些操作了

class MyType(type):def __init__(self,*args,**kwargs):super(MyType,self).__init__(*args,**kwargs)def __call__(self, *args, **kwargs):obj = self.__new__(self,*args, **kwargs) # object.__init__(....)obj.__init__(*args, **kwargs)# self.__init__(obj,*args, **kwargs)return objclass Foo(object,metaclass=MyType):def __init__(self):print('xxx')# 1. 类是MyType的对象。由MyType(...)
# 2. Foo()
obj = Foo()
print(obj)

注意在python2中metaclass的写法不同:

# python3
class Foo(object,metaclass=MyType):pass # python2
class Foo(object):__metaclass__ = MyType

补充:

metaclass的作用:就是用来指定当前类由谁创建,对派生类也是一样的,也就是当父类指定了metaclass以后,它的派生类也得由metaclass指定的类来创建

第二种指定metaclass类的方法

class MyType(type):def __init__(self, *args, **kwargs):super(MyType, self).__init__(*args, **kwargs)def __call__(cls, *args, **kwargs):print('xxxx')return super(MyType, cls).__call__(*args, **kwargs)# Foo继承的类是由MyType创建的,所以Foo类继承这个创建出来的类,那Foo的metaclass也是MyType
class Foo(MyType('Base', (object,), {})):pass
obj = Foo()

第三种指定metaclass类的方法

class MyType(type):def __init__(self, *args, **kwargs):super(MyType, self).__init__(*args, **kwargs)def __call__(cls, *args, **kwargs):return super(MyType, cls).__call__(*args, **kwargs)def with_metaclass(base):return MyType('XX', (base,), {})# Foo继承的是with_metaclass函数的返回值,返回值仍是由MyType创建的一个类
# 所以Foo作为创建出来的类的派生类,Foo的metaclass也是MyType
class Foo(with_metaclass(object)):pass

总结:类和对象加括号时的流程

类是type创建的,所以说类就是type的一个对象,而type又是由object创建的

我们创建类的时候实际上就是写type(),那这样的话就会调用object的__call__方法,在这个方法中会调用type的__new__和__init___方法

我们实例类对象时就是写类(),那这样的话就会调用type的__call__方法,在这个方法中会调用类的__new__和__init__方法

转载于:https://www.cnblogs.com/wanghl1011/articles/8584186.html

3月16日学习内容整理:metaclass相关推荐

  1. 1月16日学习内容整理:爬虫框架:Scrapy

    @@@老师博客地址::::: http://www.cnblogs.com/linhaifeng/articles/7811861.html 一.介绍 Scrapy一个开源和协作的框架,其最初是为了页 ...

  2. 1月16日学习内容整理:存储库MongoDB之文档的增删改查操作补充

    文档操作 一.查 1.比较运算 # SQL:=,!=,>,<,>=,<= # MongoDB:{key:value}代表什么等于什么,"$ne"," ...

  3. 1月24日学习内容整理:Django的admin组件源码分析及流程

    一.单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用 ...

  4. 10月25日学习内容整理:数据操作:增加更新删除,单表查询操作

    >>\G是按行显示,必须是大写 >>插入数据:补充另一种插入记录的方法 -->insert into 表名1(字段1,字段2,...) select 字段1,字段2,.. ...

  5. 11月8日学习内容整理:js的引入方式,变量数据类型,运算符,流程控制,函数...

    js是一门成熟的编程语言,专门用浏览器客户端执行的语言 一.js的引入方式 1.直接在body标签中使用script标签写js语言 2.通过script标签导入js文件,<script   sr ...

  6. 9月7日学习内容整理:内置函数

    一.内置函数 1.作用域相关: (1)globals()   查看全局作用域,显示所有的变量 (2)locals()      查看局部作用域,只会显示当前函数使用的变量 2.迭代器相关: (1)it ...

  7. 9月13日学习内容整理:异常处理

    一.异常处理 1.排错:多行报错的时候,真正报错的是最下面:若报错的地方在别人的代码里,注意别人写的代码是不会报错的,还是找自己的错 2.特点:一旦发生异常,程序不会再向下执行 3.处理方法: (1) ...

  8. 2月1日学习内容整理:算法

    1.概念 一个计算过程,解决问题的方法 2.时间复杂度和空间复杂度 时间复杂度:用来表示算法的运行效率 >>>一般来说,时间复杂度高的算法比时间复杂度低的算法运行效率高,,但这不是绝 ...

  9. 11月17日学习内容整理:jquery文档处理,事件细讲,动画

    一.文档处理:下面举例中的B可以是标签也可以是选择器也可以是字符串 >>>添加到指定元素内部的后面 $(A).append(B) // 把B放到A内部元素的最后,A是父节点$(A). ...

最新文章

  1. IoT勒索软件会演化为劫持软件
  2. EventBus3.0源码解析
  3. handler消息机制入门
  4. linux命令拉取windows的文件,find命令、文件名后缀以及Linux和Windows互传文件(示例代码)...
  5. [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段
  6. freemodbus线圈中的位操作
  7. myeclipse中的classpath .
  8. 北航计算机组成原理ppt,北航计算机组成原理课件.ppt
  9. (十四)nodejs循序渐进-高性能游戏服务器框架pomelo之开发Treasures游戏
  10. 部署到gcp_剖析大数据公司为什么选择 GCP?
  11. js 通用 1000 金额 三位格式化 1,000
  12. python如何读取二进制文件为图片_python读取图片,并获取每个像素点的二进制值...
  13. LTE学习:同步信号
  14. SQL2043N 与 linux的randomize_va_space特性
  15. 软考中级数据库系统工程师备考经验分享
  16. 达梦数据库错误号6002:消息校验异常
  17. 计算机无本地安全策略,如何打开本地安全策略、如何解决“未授予用户在此计算机上的请求登录类型”...
  18. C语言指数函数应用pow n次方
  19. python高阶学习之一:c++调用python
  20. 第六章 颠覆与重塑思维,大数据与思维革命

热门文章

  1. boost::geometry::transform用法的测试程序
  2. boost::function_types::has_property_tag用法的测试程序
  3. GDCM:制作模板的测试程序
  4. DCMTK:简单存储服务类提供者
  5. VTK:InfoVis之MutableGraphHelper
  6. OpenCV用ArUco和ChArUco进行校准
  7. OpenGL键盘消息实例
  8. C语言给定数字n阶乘的末尾计算零个数(附完整源码)
  9. C语言求最大公约数欧几里得Euclid算法(附完整源码)
  10. QT的QWaitCondition类的使用