1.python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候会创建一个对象(这里的对象指的是类而非类的实例)

  1. class Foo: #class语法后面跟一个类Foo,这个类本身也是一个对象
  2. pass
  3.  
  4. #f1是通过Foo类实例化的对象
  5. f1=Foo()
  6. #通过type查看f1这个对象由哪一个类产生
  7. print(type(f1)) #输出:<class '__main__.Foo'> f1这个对象由Foo类创建
  8. #通过type查看Foo这个类由哪一个对象产生
  9. print(type(Foo)) #输出:<class 'type'> Foo这个类的类是type,type是python的一个内置元类

返回:
<class '__main__.Foo'>
<class 'type'>
2.什么是元类(用来产生class后面定义那个类的类)
(1)元类是类的类,是类的模版
(2)元类是用来控制如何创建类的,正如类是创建对象的模版一样
(3)元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是type类的一个实例)
(4)typy是python的一个内建元类(不指定类的类是谁默认用typy去生成),用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象
3.创建元类的两种方式
方式一:利用关键字的方式声明一个类

  1. class Foo:
  2. def __init__(self): #加上构造函数__init__
  3. pass
  4.  
  5. #查看Foo这个类
  6. print(Foo)
  7. #查看Foo这个类里的属性
  8. print(Foo.__dict__)

返回:
class '__main__.Foo'>
{'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00399858>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
方式二:直接用type的方式直接实例化一个结果,这个结果相当于class声明的类

  1. def __init__(self,name,age): #顶级作用域里定义构造函数__init__
  2. self.name=name
  3. self.age=age
  4.  
  5. def test(self): #创造test方法
  6. print('我是test方法')
  7.  
  8. #创建元类FFo是由type类产生的
  9. FFo=type('FFo',(object,),{'x':1,'__init__':__init__,'test':test}) #实例化type传三个参数进去,参数1:类名字符串形式,参数2:继承的父类元祖的形式(新式类默认object),参数3:类的属性'x':1和方法属性__init__':__init__和test':test放在属性字典里
  10. #查看Foo这个类
  11. print(FFo)
  12. #用FFo这个对象产生实例传俩个参数xixi和18
  13. f1=FFo('xixi',18)
  14. #调f1的x的类属性
  15. print(f1.x) #返回:1
  16. #调f1的name的类属性
  17. print(f1.name) #返回:xixi
  18. #调f1的方法实例化
  19. f1.test() #返回:我是test方法
  20. #查看Foo这个类里的属性
  21. print(FFo.__dict__)

返回:
<class '__main__.FFo'>
1
xixi
我是test方法
{'x': 1, '__init__': <function __init__ at 0x01D8C6A8>, 'test': <function test at 0x02109858>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None}
4.一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类
5.自定制元类控制实例的生成过程

  1. #定制元类必MyType须继承type类
  2. class MyType(type):
  3. def __init__(self,a,b,c): #第二步:接收metaclass=MyType传来的四个参数,得到结果Foo,Foo这个类就此生成结束运行
  4. print('触发元类的构造函数执行')
  5. #print(a) #参数二传过来的类名
  6. #print(b) #参数三传过来继承的object
  7. #print(c) #参数四传过来类的属性字典
  8.  
  9. def __call__(self, *args, **kwargs): #第四步:接收self是Foo本身,*args, **kwargs接收Foo传的参数xixi
  10. print('触发元类里__call__方法')
  11. #print(self) #查看self是Foo:<class '__main__.Foo'>
  12. #print(args,kwargs) #查看*args, **kwargs传过来的值('xixi',) {}
  13. obj = object.__new__(self) #第五步:生成Foo的对象。所有类都继承object,object.__new__就是创建一个新的对象把self传进去,self就是Foo,得到的就是Foo这个对象,Foo产生的对象就是f1赋值给obj
  14. self.__init__(obj, *args, **kwargs) #第六步:给f1做封装的属性的事。self.__init__相当于执行Foo.__init__ 就是在执行def __init__(self,name):要传俩个参数self传obj就是f1 name传 *args, **kwargs
  15. return obj #第七步:return obj相当于return了f1。__call__得到返回值才赋值给f1
  16.  
  17. #定义Foo这个类声明它的元类是MyType,只要一class Foo会触发MyType('Foo',(object,),{})
  18. class Foo(metaclass=MyType): #第一步:执行class Foo相当于用MyType来实例化Foo,会触发class MyType(type)自己下面的__init__方法,传四个参数给__init__方法
  19. def __init__(self,name): #第八步:跳到Foo的__init__方法
  20. self.name=name #第九步:给f1封装属性,name的属性封装到f1的属性字典里。得到f1.name=name
  21.  
  22. #调用
  23. f1=Foo('xixi') #第三步:用Foo这个类名加上('xixi')在运行这个类,这个类本身就是一个对象,运行Foo('xixi')就是在调用MyType(type):里的__call__方法(因为Foo是MyType产生的) #第十步:__call__运行完毕代表Foo('xixi') 运行完毕把变量返值回给f1
  24. #查看f1
  25. print(f1)
  26. #查看f1字典里的属性
  27. print(f1.__dict__)

返回:
触发元类的构造函数执行
触发元类里__call__方法
<__main__.Foo object at 0x027C49D0>
{'name': 'xixi'}

12.python-metaclass元类的更多相关文章

  1. Python - metaclass元类

    参考 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919 ...

  2. Python - metaclass元类(图)

    个人总结

  3. python——type()、metaclass元类和精简ORM框架

    1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...

  4. python中元类(metaclass)的理解

    原文地址:http://www.cnblogs.com/tkqasn/p/6524879.html 一:类也是对象 类就是一组用来描述如何生成一个对象的代码. 类也是一个对象,只要你使用关键字clas ...

  5. python 通过元类控制类的创建

    一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...

  6. Python之元类

    类型对象负责创建对象实例,控制对象行为.那么类型对象又由谁来创建呢? 元类(metaclass)——类型的类型 New-Style Class的默认类型是type >>> class ...

  7. Python 的元类设计起源自哪里?

    一个元老级的 Python 核心开发者曾建议我们( 点击阅读),应该广泛学习其它编程语言的优秀特性,从而提升 Python 在相关领域的能力.在关于元编程方面,他的建议是学习 Hy 和 Ruby.但是 ...

  8. python基础----元类metaclass

    1 引子 class Foo: pass f1=Foo() #f1是通过Foo类实例化的对象 python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载cl ...

  9. 谈谈Python中元类Metaclass(一):什么是元类

    简单的讲,元类创建了Python中所有的对象. 我们说Python是一种动态语言,而动态语言和静态语言最大的不同,就是函数和类不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个HelloW ...

  10. 谈谈Python中元类Metaclass(二):ORM实践

    什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...

随机推荐

  1. Java基础学习-Path环境变量的配置

    1.为什么要进行Path环境变量的配置       程序的编译和执行需要使用到javac和java命令,所以只能在bin目录下写程序,而实际开发中,我们不可能将程序全部写到bin目录下,所以我们不许让 ...

  2. WebApi 运行原理

    1.当请求过来时,首先经过Global 下面的Application_start()方法,在这个方法中注册了WebApiConfig.Register 2.WebApiConfig.Register把 ...

  3. Matlab:显(隐)式Euler和Richardson外推法变步长求解刚性问题

    一.显示Euler 函数文件:Euler.m function f=Euler(h,Y) f(1,1)=Y(1)+h*(0.01-(1+(Y(1)+1000)*(Y(1)+1))*(0.01+Y(1) ...

  4. 菜鸟脱壳之脱壳的基础知识(二) ——DUMP的原理

    菜鸟脱壳之脱壳的基础知识(二)——DUMP的原理当外壳的执行完毕后,会跳到原来的程序的入口点,即Entry Point,也可以称作OEP!当一般加密强度不是很大的壳,会在壳的末尾有一个大的跨段,跳向O ...

  5. 在500jsp错误页面获取错误信息

    自定义异常发生时的错误处理页面: 1) 只要定义page指示元素的errorPage属性就可以指定当前页面发生异常时应该交给哪个页面进行处理,例如:<%@page errorPage=" ...

  6. inline元素、block元素、inline-block元素

    inline 内联元素:是不可以控制宽和高.margin等:并且在同一行显示,不换行,直到该行排满. block 块级元素:是可以控制宽和高.margin等,并且会换行.块级对象元素会单独占一行显示, ...

  7. makefile中的wildcard 、patsubst、

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效. 这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTE ...

  8. 跟随我在oracle学习php(1)

    所有的web页面都由HTML(超文本标记语言)构成,每种浏览器都将代码转换成我们所看到的页面. 这是基本上是每个程序员写的第一个代码“hello world” 这是浏览器翻译后的结果 首先<&g ...

  9. Flex 布局语法教程

    一.Flex布局是什么? Flex是Flexible Box的缩写,翻译成中文就是“弹性盒子”,用来为盒装模型提供最大的灵活性.任何一个容器都可以指定为Flex布局. .box{ display: - ...

  10. java中的\b是什么意思?

    java中有2个地方有\b,一个是特殊字符\b,另一个是在正则表达式中表示边界的意思. 我们这里只讨论特殊字符\b 我这里一共接受到几种解释: 1.退格符相当于键盘上的Backspace符号 back ...