type和metaclass元类
2024-09-06 06:16:30
元类type
1. 创建类的两种方式 (都是由type元类创建)
方式一:
class Foo(object): # 默认metaclass = type, 当前类, 由type类创建
a = 'aaa'
def func(self, x):
return x + 1
方式二:
Foo = type("Foo", (object, ), {'a': "aaa", 'func': lambda self, x: x + 1})
metaclass
作用:
通过metaclass可以指定当前类由哪一个元类创建
python2和python3的区别:
python3:
class Foo(object, metaclass=type):
pass python2:
class Foo(object):
__metaclass__=type
pass
自定义元类
1、第一步
class MyType(type):
def __init__(self, *args, **kwargs):
print("创建类之前")
super(MyType, self).__init__(*args, **kwargs)
print("创建类之后")
2、第二步
class Base(object, metaclass=MyType):
pass
或
Base = MyType('Base', (object, ), {})
这两部代码写完后,执行:
输出:
创建类之前
创建类之后
因为: 代码一执行, 就创建一个类,由MyType创建Foo类,就执行Mytype的__init__方法了
3、第三步
class Foo(Base): # 基类由MyType创建,Bar也由MyType创建
a = 'aaa' def func(self, x):
return x + 1
现在有3个类, 运行脚本,会打印2遍("创建类之前","创建类之后")
元类__new__/__init__/__call__的执行顺序
class MyType(type):
def __init__(self, *args, **kwargs):
print("MyType: __init__")
super(MyType, self).__init__(*args, **kwargs) def __call__(self, *args, **kwargs):
print('MyType: __call__')
super(MyType, self).__call__(*args, **kwargs) def with_metaclass(arg):
return MyType('Base', (arg,), {}) class Foo(with_metaclass(object)):
a = 'aaa' def __init__(self, *args, **kwargs):
print('Foo: __init__')
super(Foo, self).__init__(*args, **kwargs) def __new__(cls, *args, **kwargs):
print('Foo: __new__')
return super(Foo, cls).__new__(cls) def func(self, x):
return x + 1 b = Foo() # MyType: __init__ 这个是创建Base类的时候执行MyType的__init__
# MyType: __init__ 创建Foo类的时候,执行MyType的__init__
# MyType: __call__ 实例化 Foo(), 先执行MyType的__call__, 再执行Foo的__new__和__init__
# Foo: __new__ 然后才会执行Foo的__new__方法
# Foo: __init__ 最后执行Foo的__init__方法
总结:
1. 默认类由type实例化创建。
2. 某个类指定metaclass=MyType,那么当前类及所有派生类都由于MyType创建。
3. 实例化对象
- type.__init__
- type.__call__
- 类.__new__
- 类.__init__
最新文章
- SQL行转列+动态拼接SQL
- css布局课件
- asp.net自带的异步刷新控件使用
- 利用ExtJS导出Excel
- Android Learning:数据存储方案归纳与总结
- Java 集合框架 ArrayList 源码剖析
- MergeSort 归并排序
- 虚拟机安装CentOS6.3及常见问题总结
- 正则-匹配IP地址
- kindeditor编辑器上传图片
- RocketMQ RPC
- K1 K2作为中断源控制红色LED灯,实现任意键按一下LED灯亮或者灭
- Kubernetes中的Configmap和Secret
- 在C#中如何判断线程当前所处的状态
- mysql索引优化比普通查询速度快多少
- bzoj3676: [Apio2014]回文串 pam
- POJ 1258 Agri-Net(Prim算法求解MST)
- javascript面向对象的一些写法
- java多线程实现主线程等待子线程执行完问题
- 欢迎使用 Flask¶
热门文章
- 【学习笔记】OSG中相机参数的更改
- 初学者可能不知道的vue技巧
- C# 移动开发(Xamarin.Form) Plugin.BLE 蓝牙连接
- RPC(Remote Procedure Call Protocol)远程过程调用协议
- Android(java)学习笔记158:多线程断点下载的原理(JavaSE实现)
- Unity查找物体的四大主流方法及区别
- laravel扩展包服务提供者的注册的两种方式
- Modal 高度 在里面css里写高 | iview
- this.$refs.tabs.activeKey ref就是vue里面的id
- k8s集群之Docker安装镜像加速器配置与k8s容器网络