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实现扫描端口示例
Mar 29 Python
Python通过Pygame绘制移动的矩形实例代码
Jan 03 Python
详解Python 装饰器执行顺序迷思
Aug 08 Python
python调用百度语音识别实现大音频文件语音识别功能
Aug 30 Python
浅谈pycharm下找不到sqlalchemy的问题
Dec 03 Python
Python中文件的写入读取以及附加文字方法
Jan 23 Python
Python关键字及可变参数*args,**kw原理解析
Apr 04 Python
基于Python词云分析政府工作报告关键词
Jun 02 Python
Python简单实现词云图代码及步骤解析
Jun 04 Python
Python-for循环的内部机制
Jun 12 Python
Python进行特征提取的示例代码
Oct 15 Python
Python创建文件夹与文件的快捷方法
Dec 08 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
ajax完美实现两个网页 分页功能的实例代码
2013/04/16 PHP
ThinkPHP添加更新标签的方法
2014/12/05 PHP
Laravel 5框架学习之日期,Mutator 和 Scope
2015/04/08 PHP
PHP图片水印类的封装
2017/07/06 PHP
html超链接打开窗口大小的方法
2013/03/05 Javascript
javascript实现div浮动在网页最顶上并带关闭按钮效果实例
2013/08/13 Javascript
js实现下拉框选择要显示图片的方法
2015/02/16 Javascript
jquery实现LED广告牌旋转系统图片切换效果代码分享
2015/08/26 Javascript
js实现根据身份证号自动生成出生日期
2015/12/15 Javascript
浅析$(function) ready和onload 的区别
2016/09/03 Javascript
jQuery中animate的几种用法与注意事项
2016/12/12 Javascript
Vue.js 60分钟快速入门教程
2017/03/28 Javascript
vue bus全局事件中心简单Demo详解
2018/02/26 Javascript
vue与原生app的对接交互的方法(混合开发)
2018/11/28 Javascript
详解vue移动端项目代码拆分记录
2019/03/15 Javascript
微信小程序BindTap快速连续点击目标页面跳转多次问题处理
2019/04/08 Javascript
列举Python中吸引人的一些特性
2015/04/09 Python
python3 shelve模块的详解
2017/07/08 Python
react+django清除浏览器缓存的几种方法小结
2019/07/17 Python
django项目中使用手机号登录的实例代码
2019/08/15 Python
TensorBoard 计算图的可视化实现
2020/02/15 Python
Python调用REST API接口的几种方式汇总
2020/10/19 Python
html5+CSS3+JS实现七夕言情功能代码
2017/08/28 HTML / CSS
澳大利亚宠物食品和药物在线:Jumbo Pets
2018/03/24 全球购物
英国健身超市:Fitness Superstore
2019/06/17 全球购物
波兰化妆品和护肤品购物网站:eKobieca
2019/08/30 全球购物
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
主管会计岗位责任制
2014/02/10 职场文书
社区母亲节活动方案
2014/03/05 职场文书
暑期学习心得体会
2014/09/02 职场文书
房屋授权委托书范本
2014/10/07 职场文书
刑事辩护授权委托书范本
2014/10/17 职场文书
2015年乡镇纪委工作总结
2015/05/26 职场文书
新学期小学班主任工作计划
2019/06/21 职场文书
Python基于Tkinter开发一个爬取B站直播弹幕的工具
2021/05/06 Python
python常见的占位符总结及用法
2021/07/02 Python