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 相关文章推荐
wxPython窗口中文乱码解决方法
Oct 11 Python
Python实现把xml或xsl转换为html格式
Apr 08 Python
在Python操作时间和日期之asctime()方法的使用
May 22 Python
python目录与文件名操作例子
Aug 28 Python
Python实现压缩与解压gzip大文件的方法
Sep 18 Python
pycharm创建一个python包方法图解
Apr 10 Python
opencv-python 读取图像并转换颜色空间实例
Dec 09 Python
详解Python实现进度条的4种方式
Jan 15 Python
python实现随机加减法生成器
Feb 24 Python
Python通过socketserver处理多个链接
Mar 18 Python
python 安装库几种方法之cmd,anaconda,pycharm详解
Apr 08 Python
.img/.hdr格式转.nii格式的操作
Jul 01 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
smtp邮件发送一例
2006/10/09 PHP
兼容PHP5的PHP目录管理函数库
2008/07/10 PHP
php学习笔记 面向对象中[接口]与[多态性]的应用
2011/06/16 PHP
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
php中计算程序运行时间的类代码
2012/11/03 PHP
基于php-fpm 参数的深入理解
2013/06/03 PHP
PHP中遇到的时区问题解决方法
2015/07/23 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
2020/02/22 PHP
js 表单验证方法(实用)
2009/04/28 Javascript
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
JS操作iframe里的dom(实例讲解)
2014/01/29 Javascript
js实现大转盘抽奖游戏实例
2015/06/24 Javascript
jquery带动画效果幻灯片特效代码
2015/08/27 Javascript
三种AngularJS中获取数据源的方式
2016/02/02 Javascript
js验证真实姓名与身份证号,手机号的简单实例
2016/07/18 Javascript
js实现砖头在页面拖拉效果
2020/11/20 Javascript
原生JS实现图片轮播切换效果
2016/12/15 Javascript
JS自定义函数实现时间戳转换成date的方法示例
2017/08/27 Javascript
关于Promise 异步编程的实例讲解
2017/09/01 Javascript
Angular中的$watch方法详解
2017/09/18 Javascript
几个你不知道的技巧助你写出更优雅的vue.js代码
2018/06/11 Javascript
vue2 设置router-view默认路径的实例
2018/09/20 Javascript
vue父组件给子组件的组件传值provide inject的方法
2019/10/23 Javascript
[00:10]DOTA2全国高校联赛 以DOTA2会友
2018/05/30 DOTA
python根据路径导入模块的方法
2014/09/30 Python
使用Python写CUDA程序的方法
2017/03/27 Python
Python外星人入侵游戏编程完整版
2020/03/30 Python
python-opencv在有噪音的情况下提取图像的轮廓实例
2017/08/30 Python
利用python求解物理学中的双弹簧质能系统详解
2017/09/29 Python
FFrpc python客户端lib使用解析
2019/08/24 Python
香港太阳眼镜网上商店:SmartBuyGlasses香港
2016/07/22 全球购物
医院领导班子整改方案
2014/10/01 职场文书
群众路线自我剖析及整改措施
2014/11/04 职场文书
教务处干事工作总结
2015/08/14 职场文书
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技