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 Deque 模块使用详解
Jul 04 Python
python利用dir函数查看类中所有成员函数示例代码
Sep 08 Python
用Python将一个列表分割成小列表的实例讲解
Jul 02 Python
Django 实现图片上传和显示过程详解
Jul 18 Python
python经典趣味24点游戏程序设计
Jul 26 Python
Python浮点数四舍五入问题的分析与解决方法
Nov 19 Python
python numpy--数组的组合和分割实例
Feb 24 Python
python GUI库图形界面开发之PyQt5布局控件QHBoxLayout详细使用方法与实例
Mar 06 Python
python实现录制全屏和选择区域录屏功能
Feb 05 Python
python实现监听键盘
Apr 26 Python
python爬虫之selenium库的安装及使用教程
May 23 Python
python+pyhyper实现识别图片中的车牌号思路详解
Dec 24 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
一个自定义位数的php多用户计数器代码
2007/03/11 PHP
Django中的cookie与session操作实例代码
2017/08/17 PHP
php获取是星期几的的一些常用姿势
2019/12/15 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
JQuery操作表格(隔行着色,高亮显示,筛选数据)
2012/02/23 Javascript
Js实现双击鼠标自动滚动屏幕的示例代码
2013/12/14 Javascript
jQuery设置与获取HTML,文本和值的简单实例
2014/02/26 Javascript
Javascript表单验证要注意的事项
2014/09/29 Javascript
jQuery浏览器CSS3特写兼容实例
2015/01/19 Javascript
js操作滚动条事件实例
2015/01/29 Javascript
页面get请求 中文参数方法乱码问题的快速解决方法
2016/05/31 Javascript
jQuery操作iframe中js函数的方法小结
2016/07/06 Javascript
js浏览器html5表单验证
2016/10/17 Javascript
微信小程序  生命周期详解
2016/10/27 Javascript
form表单序列化详解(推荐)
2017/08/15 Javascript
手把手教你 CKEDITOR 4 扩展插件制作
2019/06/18 Javascript
npm 语义版本控制详解
2019/09/10 Javascript
细述Javascript的加法运算符的具体使用
2019/10/18 Javascript
原生js生成图片验证码
2020/10/11 Javascript
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
基于python的ini配置文件操作工具类
2019/04/24 Python
Django框架首页和登录页分离操作示例
2019/05/28 Python
详解使用python绘制混淆矩阵(confusion_matrix)
2019/07/14 Python
基于Python实现船舶的MMSI的获取(推荐)
2019/10/21 Python
SpringBoot实现登录注册常见问题解决方案
2020/03/04 Python
CSS+jQuery+PHP+MySQL实现的在线答题功能
2015/04/25 HTML / CSS
德国亚洲食品网上商店:asiafoodland.de
2019/12/28 全球购物
中专生自荐信
2013/10/12 职场文书
九年级英语教学反思
2014/01/31 职场文书
环境保护与污染治理求职信
2014/07/16 职场文书
刑事附带民事代理词
2015/05/25 职场文书
python使用XPath解析数据爬取起点小说网数据
2021/04/22 Python
CSS3实现列表无限滚动/轮播效果
2021/06/23 HTML / CSS
利用python做数据拟合详情
2021/11/17 Python
利用Python实现Picgo图床工具
2021/11/23 Python
Mybatis-Plus 使用 @TableField 自动填充日期
2022/04/26 Java/Android