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 相关文章推荐
Eclipse + Python 的安装与配置流程
Mar 05 Python
python持久性管理pickle模块详细介绍
Feb 18 Python
Python中的hypot()方法使用简介
May 18 Python
Python检测网站链接是否已存在
Apr 07 Python
Python调用ctypes使用C函数printf的方法
Aug 23 Python
12个Python程序员面试必备问题与答案(小结)
Jun 24 Python
pandas数据处理进阶详解
Oct 11 Python
wxpython实现按钮切换界面的方法
Nov 19 Python
python3 正则表达式基础廖雪峰
Mar 25 Python
opencv读取视频并保存图像的方法
Jun 04 Python
python函数的两种嵌套方法使用
Apr 02 Python
Python四款GUI图形界面库介绍
Jun 05 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
mongo Table类文件 获取MongoCursor(游标)的实现方法分析
2013/07/01 PHP
PHP中Header使用的HTTP协议及常用方法小结
2014/11/04 PHP
php表单提交实例讲解
2015/11/12 PHP
JS array 数组详解
2009/03/22 Javascript
javascript延时加载之defer测试
2012/12/28 Javascript
javascript 实现键盘上下左右功能的小例子
2013/09/15 Javascript
js 上下左右键控制焦点(示例代码)
2013/12/14 Javascript
jQuery过滤选择器:not()方法使用介绍
2014/04/20 Javascript
js加入收藏夹代码(兼容ie/ff/op)
2014/05/16 Javascript
JS简单实现点击复制链接的方法
2016/08/03 Javascript
jQuery实现图片轮播效果代码
2016/09/27 Javascript
基于JS实现翻书效果的页面切换样式
2017/02/16 Javascript
基于nodejs实现微信支付功能
2017/12/20 NodeJs
swiper动态改变滑动内容的实现方法
2018/01/17 Javascript
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
微信小程序里引入SVG矢量图标的方法
2019/09/20 Javascript
vue-cli设置css不生效的解决方法
2020/02/07 Javascript
Vue中实现回车键切换焦点的方法
2020/02/19 Javascript
[54:10]完美世界DOTA2联赛PWL S2 Magma vs FTD 第二场 11.29
2020/12/03 DOTA
Python网络编程之TCP与UDP协议套接字用法示例
2018/02/02 Python
python 获取list特定元素下标的实例讲解
2018/04/09 Python
Pandas之groupby( )用法笔记小结
2019/07/23 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
致跳远运动员广播稿
2014/02/11 职场文书
中西医专业毕业生职业规划书
2014/02/24 职场文书
网站客服岗位职责
2014/04/05 职场文书
借款协议书
2014/04/12 职场文书
运动会稿件100字
2014/09/24 职场文书
2015年招商引资工作总结
2015/04/25 职场文书
少年派的奇幻漂流观后感
2015/06/08 职场文书
小学班级管理心得体会
2016/01/07 职场文书
浅析MongoDB之安全认证
2021/06/26 MongoDB
企业开发CSS命名BEM代码规范实践
2022/02/12 HTML / CSS
Spring Boot 底层原理基础深度解析
2022/04/03 Java/Android
CentOS7安装GlusterFS集群以及相关配置
2022/04/12 Servers
微信小程序调用python模型
2022/04/21 Python