Python如何定义有可选参数的元类


Posted in Python onJuly 31, 2020

问题

你想定义一个元类,允许类定义时提供可选参数,这样可以控制或配置类型的创建过程。

解决方案

在定义类的时候,Python允许我们使用 ``metaclass``关键字参数来指定特定的元类。 例如使用抽象基类:

from abc import ABCMeta, abstractmethod
class IStream(metaclass=ABCMeta):
  @abstractmethod
  def read(self, maxsize=None):
    pass

  @abstractmethod
  def write(self, data):
    pass

然而,在自定义元类中我们还可以提供其他的关键字参数,如下所示:

class Spam(metaclass=MyMeta, debug=True, synchronize=True):
  pass

为了使元类支持这些关键字参数,你必须确保在 __prepare__() , __new__() __init__() 方法中 都使用强制关键字参数。就像下面这样:

class MyMeta(type):
  # Optional
  @classmethod
  def __prepare__(cls, name, bases, *, debug=False, synchronize=False):
    # Custom processing
    pass
    return super().__prepare__(name, bases)

  # Required
  def __new__(cls, name, bases, ns, *, debug=False, synchronize=False):
    # Custom processing
    pass
    return super().__new__(cls, name, bases, ns)

  # Required
  def __init__(self, name, bases, ns, *, debug=False, synchronize=False):
    # Custom processing
    pass
    super().__init__(name, bases, ns)

讨论

给一个元类添加可选关键字参数需要你完全弄懂类创建的所有步骤, 因为这些参数会被传递给每一个相关的方法。 __prepare__() 方法在所有类定义开始执行前首先被调用,用来创建类命名空间。 通常来讲,这个方法只是简单的返回一个字典或其他映射对象。 __new__() 方法被用来实例化最终的类对象。它在类的主体被执行完后开始执行。 __init__() 方法最后被调用,用来执行其他的一些初始化工作。

当我们构造元类的时候,通常只需要定义一个 __new__() __init__() 方法,但不是两个都定义。 但是,如果需要接受其他的关键字参数的话,这两个方法就要同时提供,并且都要提供对应的参数签名。 默认的 __prepare__() 方法接受任意的关键字参数,但是会忽略它们, 所以只有当这些额外的参数可能会影响到类命名空间的创建时你才需要去定义 __prepare__() 方法。

通过使用强制关键字参数,在类的创建过程中我们必须通过关键字来指定这些参数。

使用关键字参数配置一个元类还可以视作对类变量的一种替代方式。例如:

class Spam(metaclass=MyMeta):
  debug = True
  synchronize = True
  pass

将这些属性定义为参数的好处在于它们不会污染类的名称空间, 这些属性仅仅只从属于类的创建阶段,而不是类中的语句执行阶段。 另外,它们在 __prepare__() 方法中是可以被访问的,因为这个方法会在所有类主体执行前被执行。 但是类变量只能在元类的 __new__()__init__() 方法中可见。

以上就是Python如何定义有可选参数的元类的详细内容,更多关于Python定义元类的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
用Python写的图片蜘蛛人代码
Aug 27 Python
Python学习笔记(一)(基础入门之环境搭建)
Jun 05 Python
解决matplotlib库show()方法不显示图片的问题
May 24 Python
利用arcgis的python读取要素的X,Y方法
Dec 22 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
Feb 13 Python
使用Python的SymPy库解决数学运算问题的方法
Mar 27 Python
Python CVXOPT模块安装及使用解析
Aug 01 Python
Python全局锁中如何合理运用多线程(多进程)
Nov 06 Python
pytorch 图像中的数据预处理和批标准化实例
Jan 15 Python
QML用PathView实现轮播图
Jun 03 Python
python中setuptools的作用是什么
Jun 19 Python
python中not、and和or的优先级与详细用法介绍
Nov 03 Python
Python爬虫爬取糗事百科段子实例分享
Jul 31 #Python
Python如何对齐字符串
Jul 30 #Python
Python3爬虫关于代理池的维护详解
Jul 30 #Python
Python读写压缩文件的方法
Jul 30 #Python
Python3爬虫里关于代理的设置总结
Jul 30 #Python
Python 如何创建一个简单的REST接口
Jul 30 #Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
Jul 30 #Python
You might like
全局记录程序片段的运行时间 正确找到程序逻辑耗时多的断点
2011/01/06 PHP
php数组函数序列之array_values() 获取数组元素值的函数与方法
2011/10/30 PHP
php url路由入门实例
2014/04/23 PHP
分享常见的几种页面静态化的方法
2015/01/08 PHP
PHP使用flock实现文件加锁的方法
2015/07/01 PHP
javaScript同意等待代码实现心得
2011/01/01 Javascript
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
2011/10/24 Javascript
jQuery的选择器中的通配符使用介绍
2014/03/20 Javascript
jQuery中wrapInner()方法用法实例
2015/01/16 Javascript
JavaScript父子窗体间的调用方法
2015/03/31 Javascript
基于vue实现分页/翻页组件paginator示例
2017/03/09 Javascript
JavaScript基于扩展String实现替换字符串中index处字符的方法
2017/06/13 Javascript
JavaScript事件方法(实例讲解)
2017/06/27 Javascript
Angular在模板驱动表单中自定义校验器的方法
2017/08/09 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
2017/11/07 Javascript
Vue使用vux-ui自定义表单验证遇到的问题及解决方法
2018/05/10 Javascript
layui实现把数据表格时间戳转换为时间格式的例子
2019/09/12 Javascript
详解template标签用法(含vue中的用法总结)
2021/01/12 Vue.js
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
[03:24][TI9纪实] Dota奶爸
2019/08/22 DOTA
[51:53]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第二场 1月24日
2021/03/11 DOTA
Python实现在Linux系统下更改当前进程运行用户
2015/02/04 Python
python实现windows下文件备份脚本
2018/05/27 Python
python实现二维数组的对角线遍历
2019/03/02 Python
Python面向对象之Web静态服务器
2019/09/03 Python
PYTHON绘制雷达图代码实例
2019/10/15 Python
Django 自定义权限管理系统详解(通过中间件认证)
2020/03/11 Python
化学教师教学反思
2014/01/17 职场文书
森林病虫害防治方案
2014/06/02 职场文书
音乐学专业求职信
2014/07/22 职场文书
小学国旗下的演讲稿
2014/08/28 职场文书
党在我心中的演讲稿
2014/09/13 职场文书
银行先进个人总结
2015/02/15 职场文书
学术会议开幕词
2016/03/03 职场文书
MySQL连接查询你真的学会了吗?
2021/06/02 MySQL
angular4实现带搜索的下拉框
2022/03/25 Javascript