Python基础之面向对象:8、面向对象之元类

这篇具有很好参考价值的文章主要介绍了Python基础之面向对象:8、面向对象之元类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录
  • 面向对象之元类
    • 一、什么是元类
    • 二、元类推导流程
    • 三、创建类的方式
      • 方式一:
      • 方式二:
    • 四、元类定制类的产生行为
    • 五、元类定制对象的产生行为
    • 六、元类之双下new

面向对象之元类

一、什么是元类

  • Python中一切皆为对象,对象是有类实例化生成;
  • 类也是对象(类对象),生成类对象的类可称之为元类;
  • 所以,元类就是来创建类对象的,可称之为类工厂;
  • type是python内建元类,type是最上层的元类,也可称为一切类对象的元类

二、元类推导流程

"""推导步骤1:如何查看数据的数据类型"""
# s1 = 'hello world'  # str()
# l1 = [11, 22, 33, 44]  # list()
# d1 = {'name': 'jason', 'pwd': 123}  # dict()
# t1 = (11, 22, 33, 44)  # tuple()
# print(type(s1))  # <class 'str'>
# print(type(l1))  # <class 'list'>
# print(type(d1))  # <class 'dict'>
# print(type(t1))  # <class 'tuple'>

"""推导步骤2:其实type方法是用来查看产生对象的类名"""
# class Student:
#     pass
# obj = Student()
# print(type(obj))  # <class '__main__.Student'>

"""推导步骤3:python中一切皆对象 我们好奇type查看类名显示的是什么"""
class Student:
    pass
obj = Student()
print(type(obj))  # <class '__main__.Student'>
print(type(Student))  # <class 'type'>
class A:pass
class B:pass
print(type(A), type(B))

"""
结论:我们定义的类其实都是由type类产生的>>>:元类(产生类的类)
"""

三、创建类的方式

方式一:

创建方法:

​ 直接使用class关键字创建

class Foo:

    school_name = 'kangkang

    def func1(self):
        pass

    print(Teacher)
    print(Teacher.__dict__)

方式二:

创建方法:

​ 使用元类type

​ type(类名, 类的父类, 类的名称空间)

cls = type('Student', (object,), {'name':'jason'})
print(cls)
print(cls.__dict__)

"""
1.手动写键值对
    针对绑定方法不好定义
2.内置方法exec
    能够运行字符串类型的代码并产生名称空间
"""

四、元类定制类的产生行为

​ 通过上述推导,我们得出了我们所创建的类,其实就是type帮我们所生成的,那么我们是否可以通过继承type(元类)的方式,来研究type底层代码原理,来改修,新增条件,来定制类的生成

例如:

​ 生成类时,类名的首字母必须大写,否则报错

推导流程:

"""
推导
	1、对象是由类名加括号产生的  	__init__
	2、类是由元类加括号产生的		__init__
	3、查看type底层源码,找到__init__
        __init__(cls, what, bases=None, dict=None)
        cls:元类本身
        what:需要产生的类名
        bases:产生类的父类
        dict:类体名称空间
	4、通过上述我们就可以发现what可以控制类名的产生
	
"""

# 1、首先生成一个类,继承元类(type) 
    class MyMetaClass(type):
        pass
    
# 2、在类中,创建def __init__(self, what, bases=None, dict=None):
# 3、对限制what产生类名的条件
	class MyMetaClass(type):
        
    def __init__(self, what, bases=None, dict=None):
        
        # 设置条件,未满足时,主动抛出异常并提示
        if not what.istitle():
            raise TypeError('类的首字母要大写')
            
        # 条件满足后调用父类进行产生
        super().__init__(what, bases, dict)

# 4、指定类的元类:利用关键字metaclass指定类的元类
class myclass(metaclass=MyMetaClass):
    desc = '元类其实很有趣 就是有点绕'

class Student(metaclass=MyMetaClass):
    info = '我是学生 我很听话'
print(Student)
print(Student.__dict__)

# 5、这个时候我们在生成MyMetaClass的子类时,就必须要遵循它的条件,否则将会报错

五、元类定制对象的产生行为

要求:

​ 生成的对象必须使用关键字进行传参,否则将无法生成对象

推导流程:

'''
推导:
	1、我们在上述学习了类的魔法方法,发现:
	2、对象加括号会执行产生该对象类里的__call__
	3、类加括号会执行产生该类的类里的__call__
	4、观察__call__(self, *args, **kwargs):
		self: 调用者本身
		*args:接收位置实参
		**kwargs:接收关键字实参
	5、得出结论,我们需要对args进行约束就可达到条件
'''

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        
        # 1.产生一个空对象(骨架)
        # 2.调用__init__给对象添加独有的数据(血肉)
        # 3.返回创建好的对象
        # print(args)  # ('jason', 18, 'male')
        # print(kwargs)  # {}
        
 		  # 设置条件
        if args:
        # 当条件未满足时,主动抛出异常,并提升
            raise TypeError("需要进行关键字传参")
            
        # 条件满足后执行,使用super,重新调用父类
        return super().__call__(*args, **kwargs)
    	


class Student(metaclass=MyMetaClass):
    def __init__(self, name, age, gender):
        # print('__init__')
        self.name = name
        self.age = age
        self.gender = gender


# obj = Student('jason', 18, 'male')
obj = Student(name='jason',age= 18,gender= 'male')
print(obj.__dict__)

六、元类之双下new

​ 当我们在使用类产生对象时,类体代码种名字产生的顺序是:

​ __ call __ >>>: __ new __ >>>:__ init __

​ 双下call将类名传给双下new,然后new将对象的名字传给双下init而后产生类名

​ 得出结论:对象是由new进行产生的文章来源地址https://www.toymoban.com/news/detail-807315.html

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        
        # 1.产生一个空对象(骨架)
        obj = self.__new__(self)
        
        # 2.调用__init__给对象添加独有的数据(血肉)
        self.__init__(obj,*args, **kwargs)
        
        # 3.返回创建好的对象
        return obj


class Student(metaclass=MyMetaClass):
    def __init__(self, name):
        self.name = name

obj = Student('jason')
print(obj.name)
"""
__new__可以产生空对象
"""

到了这里,关于Python基础之面向对象:8、面向对象之元类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • python_面向对象基础_数据分析

    对于文本格式和JSON格式数据进行分析,将其中数据提炼出来绘制折线图。 1.设计一个完成对数据的封装 2.设计一个抽象类,定义数据读取相关功能,使用其子类实现具体功能 3.读取文件,生成数据对象 4.进行数据计算 5.绘制图表 充分使用类中的成员属性和成员方法,切实的拟合

    2024年02月14日
    浏览(46)
  • Python基础-11 面向对象编程_各种方法

    python本身支持类的动态属性 直接使用等号=,给一个属性赋值 如果这个属性存在,则会修改该属性的值 如果这个属性不存在,则会给对象添加一个新的属性及对应的值 如果需要禁止动态添加类的属性,可以使用 __slots__ 属性,如下示例 这个属性直接定义在类中,是一个元组,用来规定

    2023年04月17日
    浏览(43)
  • Python面向对象编程(一)类的基础,关系,继承,封装,多态

    类的一些理论概念及其应用场景等基础内容此处不赘述 目录 python中一切皆对象 类的定义及基础 属性 方法 初始化方法  普通方法 类之间的关系 相互调用 依赖关系 关联关系 组合关系 三大特征----类的继承 重写父类方法 多继承 混合继承  三大特征----封装 三大特征----多态

    2024年02月10日
    浏览(74)
  • python 面向对象的概念及使用方法~(基础小知识)

    编程语言中,一般有两种编程思维,面向过程和面向对象。 面向过程,看重的是解决问题的过程。 这好比我们解决日常生活问题差不多,分析解决问题的步骤,然后一步一步的解决。 而面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 Python 就是一门面向

    2024年02月06日
    浏览(49)
  • 🔥🔥Java开发者的Python快速进修指南:面向对象基础

    当我深入学习了面向对象编程之后,我首先感受到的是代码编写的自由度大幅提升。不同于Java中严格的结构和约束,Python在面向对象的实现中展现出更加灵活和自由的特性。它使用了一些独特的,如self和cls,这些不仅增强了代码的可读性,还提供了对类和实例的明确

    2024年02月05日
    浏览(64)
  • 2.python设计模式【面向对象设计的SOLID原则 基础概念】

    概念:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应该尽量在不修改原有代码的情况下进行扩展 概念:所有引用父类的地方必须能透明地使用其子类的对象 概念:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不依赖细节;细节

    2024年02月16日
    浏览(48)
  • 10天玩转Python第6天:python 函数和面向对象基础 全面详解与代码示例

    不定长参数补充-函数调用时的拆包 匿名函数 语法 代码 练习 匿名函数作为函数的参数 - 列表中的字典排序 字符串比大小 基本的介绍 面向过程 关注的是 具体步骤的实现, 所有的功能都自己书写 亲力亲为 定义一个个函数, 最终按照顺序调用函数 面向对象 关注的是结果, 谁

    2024年02月04日
    浏览(58)
  • 1746_Perl中面向对象的目录处理模块

    全部学习汇总: GreyZhang/perl_basic: some perl basic learning notes. (github.com)          说起来我还不懂Perl的面向对象编程技术,只是在前阵子看到了书中提到了一句,用到了一个例子。今天看书的时候又看到了类型形势的代码(代码中很多瘦箭头),我觉得大概是面向对象的编程

    2024年02月10日
    浏览(43)
  • Qt之元对象metaObject

    什么是元对象昂?在qt中元对象就是可以描述其它对象结构的对象,例如获取其它对象类的名称,一个对象下有多少成员函数,有哪些属性等。元对象的类QMetaObject。要使用元对象必须要满足以下几个条件: 必须要是QObject的子类 类的声明中必须包含Q_OBJECT宏 元对象编译器(

    2024年02月09日
    浏览(30)
  • Java面向对象程序设计实验报告(实验二 面向对象基础练习)

     ✨ 作者: 命运之光  ✨  专栏:Java面向对象程序设计实验报告 目录 ✨一、需求设计 ✨二、概要设计 ✨三、详细设计 ✨四、调试结果 ✨五、测试结果 ✨附录:源程序代码(带注释) 测试类demo2 Address类 Employee类 实验二 面向对象基础练习 实验环境: Eclipse+JDK 实验目的:

    2024年02月06日
    浏览(71)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包