当前位置: 首页 > article >正文

Python类及元类的创建流程

Python类及元类的创建流程

  • 代码
  • 运行结果
  • 再看type和object的关系和约定
  • type和object具有的方法不一样
  • 看代码和运行结果,可以完全理解python的执行过程。再补充几点,

代码

class MetaCls(type):
    print('0>>>', 'MetaCls', 0)
    def __init__(self, name, bases=None, dict=None):
        print('5>>>',self, '__init__',1)
        print('     MetaCls','__init__',id(self))
        super(MetaCls,self).__init__(name, bases, dict)
    
    def __new__(cls, *args, **kwagrs):
        print('4>>',cls, '__new__',2)
        print('     args',*args)
        print('     kwagrs',**kwagrs)
        print('     MetaCls','__new__',id(cls))
        print('     MetaCls','__mro__', MetaCls.__mro__)
        return super(MetaCls, cls).__new__(cls, *args, **kwagrs)
        
    print('1>>>', 'MetaCls',3)        
        
print("========1========")

class Pa(metaclass=MetaCls):
    print('2>>>', 'Pa',4)
    def __init__(self, num):
        self.num = num
        print('7>>>', self, '__init__',5)
        print('     Pa','__init__',id(self))
    
    def __new__(cls, *args, **kwagrs):
        print('6>>>', cls, '__new__',6)
        print('     args',*args)
        print('     kwagrs',**kwagrs)
        print('     Pa','__new__',id(cls))
        print('     Pa','__mro__',Pa.__mro__)
        return super(Pa, cls).__new__(cls)
        # return object.__new__(cls)
    print('3>>>', 'Pa',7)

print("========2========")

son = Pa(10000)
print('8>>>',8)
print('     ',type(son))
print('9>>>',9)
print('     ',son.num)
print('     son',id(son))
print('10>>>',10)
metaclass = MetaCls('meta',(),{})
print('     metaclass', metaclass)
    

运行结果

0>>> MetaCls 0
1>>> MetaCls 3
========1========
2>>> Pa 4
3>>> Pa 7
4>> <class '__main__.MetaCls'> __new__ 2
     args Pa () {'__module__': '__main__', '__qualname__': 'Pa', '__init__': <function Pa.__init__ at 0xf62558>, '__new__': <function Pa.__new__ at 0xb9d520>, '__classcell__': <cell at 0xe00998: empty>}
     kwagrs
     MetaCls __new__ 12179720
     MetaCls __mro__ (<class '__main__.MetaCls'>, <class 'type'>, <class 'object'>)
5>>> <class '__main__.Pa'> __init__ 1
     MetaCls __init__ 16757312
========2========
6>>> <class '__main__.Pa'> __new__ 6
     args 10000
     kwagrs
     Pa __new__ 16757312
     Pa __mro__ (<class '__main__.Pa'>, <class 'object'>)
7>>> <__main__.Pa object at 0x926870> __init__ 5
     Pa __init__ 9594992
8>>> 8
      <class '__main__.Pa'>
9>>> 9
      10000
     son 9594992
10>>> 10
4>> <class '__main__.MetaCls'> __new__ 2
     args meta () {}
     kwagrs
     MetaCls __new__ 12179720
     MetaCls __mro__ (<class '__main__.MetaCls'>, <class 'type'>, <class 'object'>)
5>>> <class '__main__.meta'> __init__ 1
     MetaCls __init__ 11834720
     metaclass <class '__main__.meta'>

再看type和object的关系和约定

>>> object.__bases__
()

>>> object.__bases__.__bases__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute '__bases__'

>>> object.__bases__.__class__
<class 'tuple'>

>>> object.__class__
<class 'type'>

>>> type.__bases__
(<class 'object'>,)

>>> type.__class__
<class 'type'>

>>> ().__bases__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute '__bases__'

>>> ().__class__
<class 'tuple'>

>>> ().__class__.__bases__
(<class 'object'>,)

python中type和object的关系图

type和object具有的方法不一样

>>> dir(type)
['__abstractmethods__', '__annotations__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__or__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__weakrefoffset__', 'mro']

>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

看代码和运行结果,可以完全理解python的执行过程。再补充几点,

  • __new__不一定需要重写。
  • 元类可以继承于object或者type或者其他类。如果没有显式的写成父类,默认是继承于object。
  • 如果元类要调用父类的__new__和__init__,传递的参数要和父类方法的一致。注意:type和object中的方法和参数是不一定相同,比如__new__的参数。官方文档对object的说明,官方文档对type的说明
  • object没有__call__。
  • __new__中一定有return返回类或实例,__init__中没有return。
  • 推荐阅读,其中核心之一是

class Foo(object, metaclass=MyMetaclass, kwarg1=value1):

它在元类中转换为
def new(cls, clsname, bases, dct, kwargs1=default):


http://www.kler.cn/a/314313.html

相关文章:

  • idea 弹窗 delete remote branch origin/develop-deploy
  • SHA-256哈希函数
  • mysql 配置文件 my.cnf 增加 lower_case_table_names = 1 服务启动不了的原因
  • docker更改数据目录
  • 1.两数之和-力扣(LeetCode)
  • 使用API有效率地管理Dynadot域名,编辑账户中whois联系人信息
  • C#进阶-基于雪花算法的订单号设计与实现
  • [Python数据可视化] Plotly:交互式数据可视化的强大工具
  • 15.9 grafana-deployment-yaml讲解
  • 掌上高考爬虫逆向分析
  • [Python数据可视化]探讨数据可视化的实际应用:三个案例分析
  • lvs-nat模式实验详解
  • 【全网最全】2024年华为杯研赛A题成品论文获取入口(后续会更新)
  • 面试时被问的问题
  • 后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0917)
  • 新版ssh客户端无法连接旧版服务器sshd的方法
  • PHP基础语法入门指南
  • CMake中的PUBLIC、PRIVATE 和 INTERFACE用法
  • C++ | Leetcode C++题解之第423题从英文中重建数字
  • 【CPU】CPU的物理核、逻辑核、超线程判断及L1、L2、L3缓存、CacheLine和CPU的TBL说明
  • vue-入门速通
  • C++_数据结构详解
  • MATLAB入门基础篇
  • 一个安卓鸿蒙化工具
  • SpringBoot环境配置(Spring Boot Profile)
  • sql执行流程经典案例分析