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/ironpython:从入门到精通
Oct 02 Python
Python中比较特别的除法运算和幂运算介绍
Apr 05 Python
Python中使用copy模块实现列表(list)拷贝
Apr 14 Python
python常用函数详解
Sep 13 Python
Python 文件操作的详解及实例
Sep 18 Python
python机器学习理论与实战(四)逻辑回归
Jan 19 Python
Python实现自动上京东抢手机
Feb 06 Python
Python定义一个跨越多行的字符串的多种方法小结
Jul 19 Python
基于DataFrame改变列类型的方法
Jul 25 Python
python读取文件指定行内容实例讲解
Mar 02 Python
Tensorflow--取tensorf指定列的操作方式
Jun 30 Python
python基于selenium爬取斗鱼弹幕
Feb 20 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 删除无限级目录与文件代码共享
2008/11/22 PHP
php调用MySQL存储过程的方法集合(推荐)
2013/07/03 PHP
Yii中CArrayDataProvider和CActiveDataProvider区别实例分析
2016/03/02 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
2018/06/13 PHP
CodeIgniter框架实现的整合Smarty引擎DEMO示例
2019/03/28 PHP
JavaScript Object的extend是一个常用的功能
2009/12/02 Javascript
javascript字母大小写转换的4个函数详解
2014/05/09 Javascript
jQuery中click事件用法实例
2014/12/26 Javascript
JavaScript整除运算函数ceil和floor的区别分析
2015/04/14 Javascript
Node.js静态文件服务器改进版
2016/01/10 Javascript
JS中多种方式创建对象详解
2016/03/22 Javascript
jQuery双向列表选择器select版
2016/11/01 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
php简单数据库操作类的封装
2017/06/08 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
2017/10/20 Javascript
React Form组件的实现封装杂谈
2018/05/07 Javascript
解决linux下node.js全局模块找不到的问题
2018/05/15 Javascript
nodejs require js文件入口,在package.json中指定默认入口main方法
2018/10/10 NodeJs
JS浏览器BOM常见操作实例详解
2020/04/27 Javascript
简单了解JavaScript作用域
2020/07/31 Javascript
[01:23]2019完美世界全国高校联赛(春季赛)合肥全国总决赛
2019/06/10 DOTA
Python HTTP客户端自定义Cookie实现实例
2017/04/28 Python
Python 函数基础知识汇总
2018/03/09 Python
详解利用OpenCV提取图像中的矩形区域(PPT屏幕等)
2019/07/01 Python
Django和Flask框架优缺点对比
2019/10/24 Python
Python脚本导出为exe程序的方法
2020/03/25 Python
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
存储过程和sql语句的优缺点
2014/07/02 面试题
空乘英文求职信
2014/04/13 职场文书
奥巴马上海演讲稿
2014/09/10 职场文书
七年级话题作文之执着
2019/11/19 职场文书
用Python远程登陆服务器的步骤
2021/04/16 Python
vue3使用vue-router的完整步骤记录
2021/06/20 Vue.js
MYSQL如何查看操作日志详解
2022/05/30 MySQL
TypeScript 内置高级类型编程示例
2022/09/23 Javascript