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  连接字符串(join %)
Sep 06 Python
python读取json文件并将数据插入到mongodb的方法
Mar 23 Python
python使用分治法实现求解最大值的方法
May 12 Python
Python编程之微信推送模板消息功能示例
Aug 21 Python
django启动uwsgi报错的解决方法
Apr 08 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
Apr 19 Python
python numpy格式化打印的实例
May 14 Python
Python生成器generator用法示例
Aug 10 Python
Python3实现的简单工资管理系统示例
Mar 12 Python
浅谈django2.0 ForeignKey参数的变化
Aug 06 Python
关于多元线性回归分析——Python&SPSS
Feb 24 Python
文件上传服务器-jupyter 中python解压及压缩方式
Apr 22 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读取txt文件并将数据插入到数据库
2016/02/23 PHP
php xhprof使用实例详解
2019/04/15 PHP
PHP使用phpunit进行单元测试示例
2019/09/23 PHP
Jquery弹出窗口插件 LeanModal的使用方法
2012/03/10 Javascript
jquery 获取表单元素里面的值示例代码
2013/07/28 Javascript
jquery操作对象数组元素方法详解
2014/11/26 Javascript
JavaScript实现点击按钮直接打印
2016/01/06 Javascript
浅析上传头像示例及其注意事项
2016/12/14 Javascript
vue中mint-ui环境搭建详细介绍
2017/04/06 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
详解如何使用PM2将Node.js的集群变得更加容易
2017/11/15 Javascript
vue-awesome-swiper滑块插件使用方法详解
2017/11/27 Javascript
Vue学习之组件用法实例详解
2020/01/06 Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
2020/02/14 Javascript
[49:13]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第一局
2016/02/27 DOTA
Python写入数据到MP3文件中的方法
2015/07/10 Python
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
Python 查看文件的读写权限方法
2018/01/23 Python
如何使用VSCode愉快的写Python于调试配置步骤
2018/04/06 Python
对python实现合并两个排序链表的方法详解
2019/01/23 Python
对Django中的权限和分组管理实例讲解
2019/08/16 Python
python matplotlib折线图样式实现过程
2019/11/04 Python
使用Python制作新型冠状病毒实时疫情图
2020/01/28 Python
python实现opencv+scoket网络实时图传
2020/03/20 Python
使用TensorBoard进行超参数优化的实现
2020/07/06 Python
浅谈python锁与死锁问题
2020/08/14 Python
HTML5的结构和语义(3):语义性的块级元素
2008/10/17 HTML / CSS
localStorage的过期时间设置的方法详解
2018/11/26 HTML / CSS
应届毕业生个人自荐信范文
2013/11/30 职场文书
打造完美自荐信
2014/01/24 职场文书
刚毕业大学生自荐信范文
2014/02/20 职场文书
出国留学担保书
2014/05/20 职场文书
先进单位事迹材料
2014/12/25 职场文书
优秀员工演讲稿
2019/06/21 职场文书
Spring Boot 实现敏感词及特殊字符过滤处理
2021/06/29 Java/Android
游戏《我的世界》澄清Xbox版暂无计划加入光追
2022/04/03 其他游戏