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实现网站的模拟登录
Jan 04 Python
python3制作捧腹网段子页爬虫
Feb 12 Python
django 使用 request 获取浏览器发送的参数示例代码
Jun 11 Python
python根据文章标题内容自动生成摘要的实例
Feb 21 Python
Django中如何使用sass的方法步骤
Jul 09 Python
python调用其他文件函数或类的示例
Jul 16 Python
python3 selenium自动化 下拉框定位的例子
Aug 23 Python
Python定时发送天气预报邮件代码实例
Sep 09 Python
python topk()函数求最大和最小值实例
Apr 02 Python
用Python制作音乐海报
Jan 26 Python
python实现MySQL指定表增量同步数据到clickhouse的脚本
Feb 26 Python
一起来学习Python的元组和列表
Mar 13 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+jQuery 注册模块的改进(一):验证码存入SESSION
2014/10/14 PHP
PHP入门教程之日期与时间操作技巧总结(格式化,验证,获取,转换,计算等)
2016/09/11 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
php5.x禁用eval的操作方法
2018/10/19 PHP
PHP赋值的内部是如何跑的详解
2019/01/13 PHP
微信公众平台开发教程②微信端分享功能图文详解
2019/04/10 PHP
PHP基础之输出缓冲区基本概念、原理分析
2019/06/19 PHP
基于Laravel-admin 后台的自定义页面用法详解
2019/09/30 PHP
模仿JQuery sortable效果 代码有错但值得看看
2009/11/05 Javascript
Javascript学习笔记6 prototype的提出
2010/01/11 Javascript
jquery插件之easing使用
2010/08/19 Javascript
js实现日期级联效果
2014/01/23 Javascript
Javascript添加监听与删除监听用法详解
2014/12/19 Javascript
让图片跳跃起来  javascript图片轮播特效
2016/02/16 Javascript
js Canvas绘制圆形时钟效果
2017/02/17 Javascript
使用AngularJS2中的指令实现按钮的切换效果
2017/03/27 Javascript
Vue中添加手机验证码组件功能操作方法
2017/12/07 Javascript
linux环境下安装pyramid和新建项目的步骤
2013/11/27 Python
Python算法之栈(stack)的实现
2014/08/18 Python
Python实现从订阅源下载图片的方法
2015/03/11 Python
实时获取Python的print输出流方法
2019/01/07 Python
Python使用uuid库生成唯一标识ID
2020/02/12 Python
No module named ‘win32gui‘ 的解决方法(踩坑之旅)
2021/02/18 Python
加拿大女装网上购物:Reitmans
2016/10/20 全球购物
荷兰在线啤酒店:Beerwulf
2019/08/26 全球购物
网站美工岗位职责
2014/04/02 职场文书
公司请假条格式
2014/04/11 职场文书
信用社竞聘演讲稿
2014/05/16 职场文书
2014市国税局对照检查材料思想汇报
2014/09/23 职场文书
纪委书记群众路线整改措施思想汇报
2014/10/09 职场文书
银行贷款委托书范本
2014/10/11 职场文书
个人四风问题整改措施
2014/10/24 职场文书
2015年教师党员承诺书
2015/04/27 职场文书
导游词之永济鹳雀楼
2020/01/16 职场文书
tensorflow中的梯度求解及梯度裁剪操作
2021/05/26 Python
灵能百分百第三季什么时候来?
2022/03/15 日漫