python通过函数和常规类编写元类

这篇具有很好参考价值的文章主要介绍了python通过函数和常规类编写元类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 python通过函数和常规类编写元类

python可以通过函数和常规类编写元类。函数和常规类之间通过type()创建类对象。

1.1 使用简单的工厂函数

python工厂函数定义了一个外部函数,它生成并返回一个嵌套函数,所以调用工厂函数就可以得到嵌套函数的引用。参考《python嵌套函数作用域》

任何可调用对象都可以作为一个元类,比如函数,只要接收传递的参数,并且返回与目标类兼容的对象。因为可调用对象都有__call__()方法。class语句也是调用type()方法,触发__call()方法。

用法

# 定义元类
def metafunc(classname,supers,classdict):
    pass
    return type(classname,supers,classdict)
# 使用元类
class ClassB(ClassA,metaclass=metafunc)

描述

定义一个工厂函数,接收三个入参,送入到type()内置函数,并且返回type()生成的可调用对象-类对象。

手动调用type()内置函数创建类对象。参考《python元类模型和class语句协议》

classname:字符串,类名;

supers:元组,存放基类;

classdict:类属性字典;

返回:创建名字为classname的类对象,类型为type类。

根据class语句协议,class语句末尾自动调用metaclass,即type()。

示例文章来源地址https://www.toymoban.com/news/detail-807226.html

>>> def metafunc(classname,supers,classdict):
    print('工厂函数 metafunc.type:',
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
    return type(classname,supers,classdict)

>>> class ClassA:pass

>>> class ClassB(ClassA,metaclass=metafunc):
    name='梯阅线条'
    def meth(self,arg):
        pass

工厂函数 metafunc.type:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000022F388C88B0>}
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(metafunc)
<class 'function'>
>>> type(ClassB)
<class 'type'>
>>> type(cb)
<class '__main__.ClassB'>

1.2 用元类重载类创建调用

用法

# 定义
class SuperMeta(type):
    def __call__(meta,classname,supers,classdict):
        pass
        return type.__call__(meta,classname,supers,classdict)
class SubMeta(type,metaclass=SuperMeta):
    def __new__(meta,classname,supers,classdict):
        pass
        return type.__new__(meta,classname,supers,classdict)
    def __init__(Class,classname,supers,classdict):
        pass
        
# 使用
class ClassB(ClassA,metaclass=SubMeta):pass

描述

通过元类的元类重载type的__call__()方法,再显式调用type的__call__()方法,再触发type子类的__new__()和__init__()方法。

(1) 定义元类SubMeta,继承type,并且指定元类metaclass=SuperMeta;

(2) 定义元类的元类SuperMeta,继承type,重载__call__()方法;

(3) 客户类ClassB通过metaclass=SubMeta指定元类;

(4) 通过class协议触发元类SubMeta,再触发元类的元类SuperMeta的__call__()方法;

(5) SuperMeta的__call__()方法显式调用type.__call__();

(6) type.__call__()调用子类SubMeta的__new__()和__init__()方法;

(7) 子类SubMeta的__new__()方法,显式调用type的__new__()创建类对象,赋值给客户类ClassB;

示例

>>> class SuperMeta(type):
    def __call__(meta,classname,supers,classdict):
        print('调用 SuperMeta.call:',
              'meta: %s' % meta,
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        return type.__call__(meta,classname,supers,classdict)
>>> class SubMeta(type,metaclass=SuperMeta):
    def __new__(meta,classname,supers,classdict):
        print('调用 SubMeta.new:',
              'meta: %s' % meta,
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        return type.__new__(meta,classname,supers,classdict)
    def __init__(Class,classname,supers,classdict):
        print('调用 SubMeta.init:',
              'Class: %s' % Class,
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        print('初始化类对象:',list(Class.__dict__.keys()))

        
>>> class ClassA:pass

>>> class ClassB(ClassA,metaclass=SubMeta):
    name='梯阅线条'
    def meth(self,arg):
        pass

调用 SuperMeta.call:
meta: <class '__main__.SubMeta'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
调用 SubMeta.new:
meta: <class '__main__.SubMeta'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
调用 SubMeta.init:
Class: <class '__main__.ClassB'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
初始化类对象: ['__module__', 'name', 'meth', '__doc__']
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(SubMeta)
<class '__main__.SuperMeta'>
>>> type(SuperMeta)
<class 'type'>
>>> type(ClassB)
<class '__main__.SubMeta'>
>>> type(cb)
<class '__main__.ClassB'>

1.3 用常规类重载类创建调用

用法

# 定义
class SuperMeta:
    def __call__(self,classname,supers,classdict):
        Class=self.__New__(classname,supers,classdict)
        self.__Init__(Class,classname,supers,classdict)
        pass
        return Class
class SubMeta(SuperMeta):
    def __New__(self,classname,supers,classdict):
        pass
        return type(classname,supers,classdict)
    def __Init__(self,Class,classname,supers,classdict):
        pass

# 使用        
class ClassA:pass

class ClassB(ClassA,metaclass=SubMeta()):pass

描述

通过常规类模拟元类的元类,重载__call__()方法,调用子类的New方法,New显式调用type()创建类对象赋值给客户类。

(1) 定义常规类SuperMeta模拟元类的元类;

(2) SuperMeta定义__call__()方法,调用子类SubMeta的__New__()和__Init__()方法;

(3) SuperMeta返回客户类Class;

(4) 定义常规类SubMeta,继承SuperMeta,作为客户类的元类;

(5) SubMeta的__New__()方法,显式调用type()方法创建类对象,返回赋值给客户类;

(6) SubMeta的__Init__()方法,对类对象进行初始化;

(7) 定义客户类ClassB,指定元类metaclass=SubMeta()实例对象;

(8) class协议自动调用实例对象SubMeta()的__call__()方法,搜索到SuperMeta的__call__()方法,触发元类SubMeta的New和Init方法;

示例

>>> class SuperMeta:
    def __call__(self,classname,supers,classdict):
        print('调用 SuperMeta.call:',
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        Class=self.__New__(classname,supers,classdict)
        self.__Init__(Class,classname,supers,classdict)
        return Class

    
>>> class SubMeta(SuperMeta):
    def __New__(self,classname,supers,classdict):
        print('调用 SubMeta.new:',
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        return type(classname,supers,classdict)
    def __Init__(self,Class,classname,supers,classdict):
        print('调用 SubMeta.init:',
              'Class: %s' % Class,
              'classname: %s' % classname,
              'supers: %s' % supers,
              'classdict: %s' % classdict,sep='\n')
        print('初始化类对象:',list(Class.__dict__.keys()))

        
>>> class ClassA:pass

>>> class ClassB(ClassA,metaclass=SubMeta()):
    name='梯阅线条'
    def meth(self,arg):
        pass

调用 SuperMeta.call:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
调用 SubMeta.new:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
调用 SubMeta.init:
Class: <class '__main__.ClassB'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
初始化类对象: ['__module__', 'name', 'meth', '__doc__']
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(SubMeta)
<class 'type'>
>>> type(SuperMeta)
<class 'type'>
>>> type(ClassB)
<class 'type'>
>>> type(cb)
<class '__main__.ClassB'>

到了这里,关于python通过函数和常规类编写元类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 波奇学C++:友元函数,友元类,内部类,匿名对象,优化构造

    这个代码会报错,原因是_a是a._a的私有成员,fun()是类外函数不能访问。 加上友元就可以突破限制 关于友元的知识 友元函数是一种声明,表明这个函数可以访问私有变量。 友元函数本质上不属于类函数,所以这个声明是不受访问限定符限制的,可以定义在public或者private中。

    2024年02月05日
    浏览(40)
  • C //练习 4-12 运用printd函数的设计思想编写一个递归版本的itoa函数,即通过递归调用把整数转换为字符串。

    练习 4-12 运用printd函数的设计思想编写一个递归版本的itoa函数,即通过递归调用把整数转换为字符串。 注意:代码在win32控制台运行,在不同的IDE环境下,有部分可能需要变更。 IDE工具:Visual Studio 2010   代码块:

    2024年01月18日
    浏览(71)
  • Python 编写函数

    编写程序时,经常用到一些条件或判断,需要用到 if 语句,它的字面意思是:如果(if)满足条件,做什么,否则(else)做什么。例如,下面一段代码: 这段代码的意思是,如果 a 比 10 大,则输出 “Value of a is greater than 10”,否则输出 “Value of a is not greater than 10”。if 语句

    2024年02月10日
    浏览(30)
  • python烟花代码通过编写程序来模拟烟花的绽放过程

    下面是一个简单的 Python 烟花代码,可以通过编写程序来模拟烟花的绽放过程: 该代码使用 turtle 库来绘制烟花的效果。首先,设置窗口大小和标题,定义烟花的颜色和数量。然后,定义烟花的形状,采用 turtle.Shape 的方式来定义,包括圆形和尾迹。接着,注册烟花的形状,采

    2024年02月05日
    浏览(42)
  • python 元类

    我们知道在python中一切皆对象,即使是类,也是对象,那么类这个对象是的类是谁呢?那就是 元类 。 通过 type() 和 obj.__class__ 可查看对象的元类: 从上面结果可以看出: 普通对象的元类可直接查看是创建对象的类 自己创建的一些类的元类是type python内置的一些基本类型的元

    2024年02月05日
    浏览(36)
  • 深入理解Python中的元类

    所有对象都是实例化或者调用类而得到的,Python中一切都是对象,通过class定义的类本质也是对象,对象又是通过调用类得到的,因此通过class定义的类肯定也是调用了一个类得到的,这个类就是元类。type就是Python内置的元类 在理解元类之前,你需要先掌握Pyt

    2024年02月08日
    浏览(41)
  • C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 、 Linu

    2023年04月15日
    浏览(41)
  • python元类模型和class语句协议

    学习python的类型模型和class语句协议。class语句末尾自动调用type()创建类对象并且赋值给类名称。 python3.x中,用户定义的类对象是名为type的对象的实例,type本身是一个类; python2.x中,新式类继承object,它是type的一个子类;传统类是type的一个实例; type()内置函数返回任何对

    2024年01月21日
    浏览(34)
  • Python基础之面向对象:8、面向对象之元类

    目录 面向对象之元类 一、什么是元类 二、元类推导流程 三、创建类的方式 方式一: 方式二: 四、元类定制类的产生行为 五、元类定制对象的产生行为 六、元类之双下new Python中一切皆为对象,对象是有类实例化生成; 类也是对象(类对象),生成类对象的类可称之为元

    2024年01月20日
    浏览(55)
  • 系统学习Python——装饰器:类装饰器-[初探类装饰器和元类]

    分类目录:《系统学习Python》总目录 函数装饰器是如此有用,以至于Python2.X和Python3.X都扩展了这一模式,允许装饰器应用于类和函数。简而言之,类装饰器类似于函数装饰器,但它们是在一条 class 语句的末尾运行,并把一个类名重新绑定到一个可调用对象。同样,它们可以

    2024年02月19日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包