python元类使用场景_Python元类使用简介
本文概述
Python中的元类是定义类行为方式的类的类。类本身就是元类的实例。 Python中的类定义了该类实例的行为。为了更好地理解元类, 需要具有使用Python类的先验经验。在深入研究元类之前, 让我们先了解一些概念。
Python中的一切都是对象
class TestClass():
pass
my_test_class = TestClass()
print(my_test_class)
可以动态创建Python类
Python中的type使我们能够找到对象的类型。我们可以继续检查上面创建的对象的类型。
type(TestClass)
type
type(type)
type
等等, 发生了什么事?我们希望上面创建的对象的类型为class, 但事实并非如此。坚持那个想法。我们将在后面进一步介绍。我们还注意到类型本身的类型是type。它是类型的实例。该类型所做的另一个神奇的事情是使我们能够动态创建类。让我们在下面展示我们将如何做。如下所示, 将使用类型创建以下所示的srcmini类:
class srcmini():
pass
srcminiClass = type('srcmini', (), {})
print(srcminiClass)
print(srcmini())
在上面的示例中, srcmini是类名, 而srcminiClass是保存类引用的变量。使用type时, 我们可以使用字典传递类的属性, 如下所示:
PythonClass = type('PythonClass', (), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass.start_date, PythonClass.instructor)
print(PythonClass)
August 2018 John Doe
如果我们希望PythonClass继承自srcmini类, 则在使用type定义类时将其传递给第二个参数
PythonClass = type('PythonClass', (srcmini, ), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass)
现在, 这两个概念已不复存在, 我们意识到Python使用元类创建了类。我们已经看到Python中的所有东西都是一个对象, 这些对象是由元类创建的。每当我们调用class创建一个class时, 就有一个metaclass可以在后台创建class的魔力。在上面的实践中, 我们已经看到类型可以做到这一点。它类似于创建字符串的str和创建整数的int。在Python中, ___class__attribute使我们能够检查当前实例的类型。让我们在下面创建一个字符串并检查其类型。
article = 'metaclasses'
article.__class__
str
我们也可以使用type(article)检查类型。
type(article)
str
当检查str的类型时, 我们还发现它是类型。
type(str)
type
当我们检查float, int, list, tuple和dict的类型时, 我们将得到类似的输出。这是因为所有这些对象都是type类型。
print(type(list), type(float), type(dict), type(tuple))
我们已经看到类型创建类。因此, 当我们检查__class__的__class__时, 它应该返回类型。
article.__class__.__class__
type
创建自定义元类
在Python中, 我们可以通过在类定义中传递metaclass关键字来自定义类创建过程。这也可以通过继承已在此关键字中传递的类来完成。
class MyMeta(type):
pass
class MyClass(metaclass=MyMeta):
pass
class MySubclass(MyClass):
pass
在下面我们可以看到MyMeta类的类型是type, 而MyClass和MySubClass的类型是MyMeta。
print(type(MyMeta))
print(type(MyClass))
print(type(MySubclass))
当定义一个类并且没有定义元类时, 将使用默认类型的元类。如果给定一个元类, 并且它不是type()的实例, 则它将直接用作元类。
__new__和__init__
也可以通过以下两种方式之一定义元类。我们将在下面解释它们之间的区别。
class MetaOne(type):
def __new__(cls, name, bases, dict):
pass
class MetaTwo(type):
def __init__(self, name, bases, dict):
pass
__new__用于在创建类之前定义字典或基元组的情况。 __new__的返回值通常是cls的实例。 __new__允许不可变类型的子类自定义实例创建。可以在自定义元类中覆盖它以自定义类的创建。通常在创建对象之后调用__init__以便对其进行初始化。
元类__call__方法
根据官方文档, 我们还可以通过在元类中定义一个自定义__call __()方法来覆盖其他类方法, 该方法在调用该类时允许自定义行为。
元类__prepare__方法
根据Python的数据模型文档
一旦标识了适当的元类, 就准备好类名称空间。如果元类具有__prepare__属性, 则将其称为命名空间= metaclass .__ prepare __(名称, 基数, ** kwds)(其中其他关键字参数(如果有)来自类定义)。如果元类没有__prepare__attribute, 则将类名称空间初始化为空的有序映射。 -docs.python.org
使用元类的单例设计
这是一种设计模式, 用于将类的实例化限制为仅一个对象。例如, 当设计一个类以连接到数据库时, 这可能会很有用。一个人可能只想拥有一个连接类实例。
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonClass(metaclass=SingletonMeta):
pass
总结
在本文中, 我们了解了什么是元类以及如何在Python编程中实现它们。元类可以应用于日志记录, 创建时注册类以及进行概要分析。它们似乎是非常抽象的概念, 你可能想知道是否需要使用它们。长期使用Pythonista的Tim Peters最好地回答了这个问题。
“元类是比99%的用户应该担心的更深的魔力。如果你想知道是否需要它们, 则不需要(实际上需要它们的人可以肯定地知道他们需要它们, 并且不需要任何解释。为什么)。” -真正的python
如果你想了解有关Python的更多信息, 请启动srcmini的Python编程技能专区。
参考文献
链接一
链接二
python元类使用场景_Python元类使用简介相关推荐
- python元类使用场景_python 元类的使用
class Animal(object): """a class representing an animal""" def __init_ ...
- python 元类 详解_Python 元类详解 __new__、__init__、__call__、__metacalss__
了解元类之前,先了解几个魔术方法: __new__.__init__.__call__ __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪 ...
- python类的应用_Python · 元类(Meta Class)及其应用
(这里是本章用到的 GitHub 地址)万物皆对象 -- Python 本章所介绍的元类(Meta Class)和之前介绍过的装饰器(Decorator)都是上面这句话的具现,其中装饰器告诉过我们&q ...
- python元类的使用_Python 元类使用讲解
我要一大群的类都具有一种特点,我怎么给他们加上呢?模板嘛,我从这个模板创建一群类不就OK了?那就需要元类了. 定义一个元类(就是一个类的模板!莫多想,还要记住这是类级别的,不是对象级别的!): 代码如 ...
- python字典、列表、元祖使用场景_python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍...
python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍 一丶元祖 1.元祖简介 元祖跟列表类似.只不过是有区别的. 如下: tuple(元祖英文) 跟列表类似, 元素不能 ...
- python计算复数的辐角_Python 自定义类中的函数和运算符重载
如果你曾在字符串(str)对象上进行过 + 或 * 运算,你一定注意到它跟整数或浮点数对象的行为差异: >>> # 加法 >>> 1 + 2 3 >>& ...
- python中self做前缀_python 创建类和为什么类方法中self形参必不可少?
我们观察到在类中定义方法时,都带有self形参,为何必须在方法中定义形参self呢? 因为Python调用方法创建类实例时,将自动传入实参self.每个与类相关联的方法调用都自动传递实参self,他是 ...
- python新式类c3算法_Python 新式类继承关系的 C3 算法(Python 2.3 的方法解析顺序,MRO)...
Python 新式类继承关系的 C3 算法(Python 2.3 的方法解析顺序,MRO) 翻译:刘硕 摘要:本文档面向于想要了解Python 2.3版本中 C3 方法解析顺序的 Python程序开发 ...
- python中表示类的公有成员_Python面向对象 | 类的成员
一. 细分类的组成成员 之前咱们讲过类大致分两块区域,静态字段部分和方法部分. 每个区域详细划分又可以分为: classA: company= '阿里巴巴' #静态变量(静态字段) __tel = ' ...
最新文章
- SpringBoot Mybatis解决使用PageHelper一对多分页问题
- ITCAST视频-Spring学习笔记(使用JDK中的Proxy技术实现AOP功能)
- 修改centos等linux的hostname-永久生效
- DP专辑之最长公共子序列及其变形
- Openfire3.9.3源代码导入eclipse中开发配置指南(转载)
- Codeforces Round #198 (Div. 1) B,C 动态规划
- 5动态显示图片_单片机入门 数码管的静态显示和动态显示 壁纸
- 最强JAVA核心技术群
- 极限分辨率是艾里斑的直径还是半径_小孔成像(二)——衍射,数值孔径和分辨率...
- 网络安全实验室CTF—基础关 writeup
- java 应用 http spdy_java-删除了ALPN回调:禁用了SPDY和HTTP / 2. alpn-boot是否在引导类路径上?...
- 11 Mortal Fibonacci Rabbits
- PS学习总结三:修图必备的高阶操作
- android 短信接口收拦截,闪修侠科普 | 双11垃圾短信没停过,教你一键屏蔽~
- 第二篇:mig IP的创建
- 构建单拷贝同源蛋白系统发育树,一条命令提序列!
- [bzoj1127][悬线法]KUP
- 全国物流企业有哪些 物流企业详细信息怎么查询
- tf.repeat(), Tensorflow2.1.0以上
- fβ,fα,fT,fmax之间的关系
热门文章
- python+selenium之自动生成excle,保存到指定的目录下
- Android PullTorefreshScrollview回到顶部
- 201452202014520920145309信息安全系统设计基础实验报告(1)
- hadoop 学习(1):搭建环境
- 调用Android自带日历功能(日历列表单、添加一个日历事件)
- Do you want to put on or loose weight?
- 冠军奖10万日元+10公斤柠檬!一个简单的柠檬图像分级竞赛
- 刚刚,SeetaFace版本升级!新增活体检测等功能
- LFFD:轻量级人脸检测器,不止是快
- CVPR 2019 | 亮风台发布全球最大单目标跟踪数据集LaSOT