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二叉树的实现实例
Nov 21 Python
深入理解Python变量与常量
Jun 02 Python
python中类和实例如何绑定属性与方法示例详解
Aug 18 Python
python利用有道翻译实现"语言翻译器"的功能实例
Nov 14 Python
python编程测试电脑开启最大线程数实例代码
Feb 09 Python
pycharm快捷键汇总
Feb 14 Python
解决python对齐错误的方法
Jul 16 Python
Django rest framework分页接口实现原理解析
Aug 21 Python
如何利用Python给自己的头像加一个小国旗(小月饼)
Oct 02 Python
python中把元组转换为namedtuple方法
Dec 09 Python
python中altair可视化库实例用法
Jan 26 Python
Python对excel的基本操作方法
Feb 18 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读取纯真ip数据库使用示例
2014/01/26 PHP
php通过会话控制实现身份验证实例
2016/10/18 PHP
PHP jpgraph库的配置及生成统计图表:折线图、柱状图、饼状图
2017/05/15 PHP
PHP实现简单的模板引擎功能示例
2017/09/02 PHP
PHP实现登录注册之BootStrap表单功能
2017/09/03 PHP
javascript 装载iframe子页面,自适应高度
2009/03/20 Javascript
JS input 数字验证代码
2009/07/30 Javascript
Extjs中常用表单介绍与应用
2010/06/07 Javascript
JavaScript高级程序设计(第3版)学习笔记2 js基础语法
2012/10/11 Javascript
js图片轮播效果实现代码
2020/04/18 Javascript
JS提交form表单实例分析
2015/12/10 Javascript
JavaScript中的ajax功能的概念和示例详解
2016/10/17 Javascript
BootStrop前端框架入门教程详解
2016/12/25 Javascript
详解Angular.js中$http拦截器的介绍及使用
2017/07/04 Javascript
页面缩放兼容性处理方法(zoom,Firefox火狐浏览器)
2017/08/29 Javascript
详解基于mpvue的小程序markdown适配解决方案
2018/05/08 Javascript
vue中实现左右联动的效果
2018/06/22 Javascript
vue中前进刷新、后退缓存用户浏览数据和浏览位置的实例讲解
2018/09/21 Javascript
JavaScript格式化json和xml的方法示例
2019/01/22 Javascript
Vue起步(无cli)的啊教程详解
2019/04/11 Javascript
es6中let和const的使用方法详解
2020/02/24 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
python使用xlrd实现检索excel中某列含有指定字符串记录的方法
2015/05/09 Python
如何使用Python自动控制windows桌面
2019/07/11 Python
解决python3 requests headers参数不能有中文的问题
2019/08/21 Python
flask框架url与重定向操作实例详解
2020/01/25 Python
Python tkinter实现简单加法计算器代码实例
2020/05/13 Python
Python中免验证跳转到内容页的实例代码
2020/10/23 Python
Python爬虫之Selenium下拉框处理的实现
2020/12/04 Python
amaze ui 的使用详细教程
2020/08/19 HTML / CSS
Under Armour安德玛荷兰官网:美国高端运动科技品牌
2019/07/10 全球购物
bonprix匈牙利:女士、男士和儿童服装
2019/07/19 全球购物
小学开学标语
2014/07/01 职场文书
销售区域经理岗位职责
2015/04/10 职场文书
未婚证明范本
2015/06/15 职场文书
python中Pyqt5使用Qlabel标签播放视频
2022/04/22 Python